2023-05-18 13:25:19 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) Contributors to the Suwayomi project
|
|
|
|
|
*
|
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-09-01 20:21:59 +02:00
|
|
|
import {
|
2023-09-12 02:36:11 +02:00
|
|
|
ApolloError,
|
2023-09-30 16:55:35 +02:00
|
|
|
ApolloQueryResult,
|
2023-09-12 02:36:11 +02:00
|
|
|
DocumentNode,
|
2023-09-01 20:21:59 +02:00
|
|
|
FetchResult,
|
2023-10-02 16:58:32 +02:00
|
|
|
MutationHookOptions as ApolloMutationHookOptions,
|
|
|
|
|
MutationOptions as ApolloMutationOptions,
|
2023-11-24 03:20:16 +01:00
|
|
|
MutationResult,
|
2023-09-01 20:21:59 +02:00
|
|
|
MutationTuple,
|
2023-10-02 16:58:32 +02:00
|
|
|
QueryHookOptions as ApolloQueryHookOptions,
|
|
|
|
|
QueryOptions as ApolloQueryOptions,
|
2023-09-01 20:21:59 +02:00
|
|
|
QueryResult,
|
2023-10-04 22:34:32 +02:00
|
|
|
SubscriptionHookOptions as ApolloSubscriptionHookOptions,
|
|
|
|
|
SubscriptionResult,
|
2023-09-01 20:21:59 +02:00
|
|
|
TypedDocumentNode,
|
|
|
|
|
useMutation,
|
|
|
|
|
useQuery,
|
2023-10-04 22:34:32 +02:00
|
|
|
useSubscription,
|
2023-09-01 20:21:59 +02:00
|
|
|
} from '@apollo/client';
|
2024-04-27 22:28:55 +02:00
|
|
|
import { OperationVariables, Reference } from '@apollo/client/core';
|
2023-11-18 19:55:35 +01:00
|
|
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
2023-10-04 01:48:19 +02:00
|
|
|
import { IRestClient, RestClient } from '@/lib/requests/client/RestClient.ts';
|
2023-09-01 20:21:59 +02:00
|
|
|
import { GraphQLClient } from '@/lib/requests/client/GraphQLClient.ts';
|
2023-09-01 20:24:40 +02:00
|
|
|
import {
|
2023-09-01 20:39:30 +02:00
|
|
|
CategoryOrderBy,
|
2023-09-30 16:55:35 +02:00
|
|
|
ChapterOrderBy,
|
2023-09-01 20:26:06 +02:00
|
|
|
CheckForServerUpdatesQuery,
|
|
|
|
|
CheckForServerUpdatesQueryVariables,
|
2023-12-09 14:16:52 +01:00
|
|
|
ClearCachedImagesInput,
|
2023-12-09 23:08:27 +01:00
|
|
|
CheckForWebuiUpdateQuery,
|
|
|
|
|
CheckForWebuiUpdateQueryVariables,
|
2023-09-01 20:40:24 +02:00
|
|
|
ClearDownloaderMutation,
|
|
|
|
|
ClearDownloaderMutationVariables,
|
2023-12-09 14:16:52 +01:00
|
|
|
ClearServerCacheMutation,
|
|
|
|
|
ClearServerCacheMutationVariables,
|
2023-09-01 20:39:30 +02:00
|
|
|
CreateCategoryInput,
|
|
|
|
|
CreateCategoryMutation,
|
|
|
|
|
CreateCategoryMutationVariables,
|
|
|
|
|
DeleteCategoryMutation,
|
|
|
|
|
DeleteCategoryMutationVariables,
|
2023-09-01 20:36:40 +02:00
|
|
|
DeleteDownloadedChapterMutation,
|
|
|
|
|
DeleteDownloadedChapterMutationVariables,
|
|
|
|
|
DeleteDownloadedChaptersMutation,
|
|
|
|
|
DeleteDownloadedChaptersMutationVariables,
|
2023-09-01 20:40:24 +02:00
|
|
|
DequeueChapterDownloadMutation,
|
|
|
|
|
DequeueChapterDownloadMutationVariables,
|
|
|
|
|
DequeueChapterDownloadsMutation,
|
|
|
|
|
DequeueChapterDownloadsMutationVariables,
|
2023-10-04 22:34:32 +02:00
|
|
|
DownloadStatusSubscription,
|
|
|
|
|
DownloadStatusSubscriptionVariables,
|
2023-09-01 20:40:24 +02:00
|
|
|
EnqueueChapterDownloadMutation,
|
|
|
|
|
EnqueueChapterDownloadMutationVariables,
|
|
|
|
|
EnqueueChapterDownloadsMutation,
|
|
|
|
|
EnqueueChapterDownloadsMutationVariables,
|
2023-09-08 00:06:24 +02:00
|
|
|
FetchSourceMangaInput,
|
|
|
|
|
FetchSourceMangaType,
|
|
|
|
|
FilterChangeInput,
|
2023-09-01 20:25:46 +02:00
|
|
|
GetAboutQuery,
|
|
|
|
|
GetAboutQueryVariables,
|
2023-09-01 20:39:30 +02:00
|
|
|
GetCategoriesQuery,
|
|
|
|
|
GetCategoriesQueryVariables,
|
2023-10-27 20:15:03 +02:00
|
|
|
GetCategoryMangasQuery,
|
|
|
|
|
GetCategoryMangasQueryVariables,
|
2023-09-30 16:55:35 +02:00
|
|
|
GetChapterPagesFetchMutation,
|
|
|
|
|
GetChapterPagesFetchMutationVariables,
|
|
|
|
|
GetChaptersQuery,
|
|
|
|
|
GetChaptersQueryVariables,
|
2023-10-16 01:38:53 +02:00
|
|
|
GetExtensionsFetchMutation,
|
|
|
|
|
GetExtensionsFetchMutationVariables,
|
2023-09-01 20:28:23 +02:00
|
|
|
GetExtensionsQuery,
|
|
|
|
|
GetExtensionsQueryVariables,
|
2023-09-01 20:24:40 +02:00
|
|
|
GetGlobalMetadatasQuery,
|
|
|
|
|
GetGlobalMetadatasQueryVariables,
|
2023-11-19 22:43:29 +01:00
|
|
|
GetLastUpdateTimestampQuery,
|
|
|
|
|
GetLastUpdateTimestampQueryVariables,
|
2023-09-30 16:55:35 +02:00
|
|
|
GetMangaChaptersFetchMutation,
|
|
|
|
|
GetMangaChaptersFetchMutationVariables,
|
2023-09-08 00:44:01 +02:00
|
|
|
GetMangaFetchMutation,
|
|
|
|
|
GetMangaFetchMutationVariables,
|
|
|
|
|
GetMangaQuery,
|
|
|
|
|
GetMangaQueryVariables,
|
2023-10-19 21:01:21 +02:00
|
|
|
GetMangasQuery,
|
|
|
|
|
GetMangasQueryVariables,
|
2023-10-29 01:49:27 +02:00
|
|
|
GetRestoreStatusQuery,
|
|
|
|
|
GetRestoreStatusQueryVariables,
|
2023-10-27 23:39:05 +02:00
|
|
|
GetServerSettingsQuery,
|
2023-09-08 00:06:24 +02:00
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables,
|
2023-09-01 20:29:19 +02:00
|
|
|
GetSourceQuery,
|
|
|
|
|
GetSourceQueryVariables,
|
|
|
|
|
GetSourcesQuery,
|
|
|
|
|
GetSourcesQueryVariables,
|
2023-09-01 20:40:39 +02:00
|
|
|
GetUpdateStatusQuery,
|
|
|
|
|
GetUpdateStatusQueryVariables,
|
2023-09-01 20:28:23 +02:00
|
|
|
InstallExternalExtensionMutation,
|
|
|
|
|
InstallExternalExtensionMutationVariables,
|
2023-09-01 20:40:24 +02:00
|
|
|
ReorderChapterDownloadMutation,
|
|
|
|
|
ReorderChapterDownloadMutationVariables,
|
2023-10-04 01:17:10 +02:00
|
|
|
RestoreBackupMutation,
|
|
|
|
|
RestoreBackupMutationVariables,
|
2023-09-01 20:39:30 +02:00
|
|
|
SetCategoryMetadataMutation,
|
|
|
|
|
SetCategoryMetadataMutationVariables,
|
2023-09-01 20:36:40 +02:00
|
|
|
SetChapterMetadataMutation,
|
|
|
|
|
SetChapterMetadataMutationVariables,
|
2023-09-01 20:24:40 +02:00
|
|
|
SetGlobalMetadataMutation,
|
|
|
|
|
SetGlobalMetadataMutationVariables,
|
2023-09-01 20:33:35 +02:00
|
|
|
SetMangaMetadataMutation,
|
2023-10-09 20:41:58 +02:00
|
|
|
SetMangaMetadataMutationVariables,
|
2023-09-30 16:55:35 +02:00
|
|
|
SortOrder,
|
2023-09-25 23:32:26 +02:00
|
|
|
SourcePreferenceChangeInput,
|
2023-09-01 20:40:24 +02:00
|
|
|
StartDownloaderMutation,
|
|
|
|
|
StartDownloaderMutationVariables,
|
|
|
|
|
StopDownloaderMutation,
|
|
|
|
|
StopDownloaderMutationVariables,
|
2023-09-01 20:40:39 +02:00
|
|
|
StopUpdaterMutation,
|
|
|
|
|
StopUpdaterMutationVariables,
|
|
|
|
|
UpdateCategoryMangasMutation,
|
|
|
|
|
UpdateCategoryMangasMutationVariables,
|
2023-09-01 20:39:30 +02:00
|
|
|
UpdateCategoryMutation,
|
|
|
|
|
UpdateCategoryMutationVariables,
|
|
|
|
|
UpdateCategoryOrderMutation,
|
|
|
|
|
UpdateCategoryOrderMutationVariables,
|
|
|
|
|
UpdateCategoryPatchInput,
|
2023-09-01 20:36:40 +02:00
|
|
|
UpdateChapterMutation,
|
|
|
|
|
UpdateChapterMutationVariables,
|
|
|
|
|
UpdateChapterPatchInput,
|
|
|
|
|
UpdateChaptersMutation,
|
|
|
|
|
UpdateChaptersMutationVariables,
|
2023-09-01 20:28:23 +02:00
|
|
|
UpdateExtensionMutation,
|
|
|
|
|
UpdateExtensionMutationVariables,
|
|
|
|
|
UpdateExtensionPatchInput,
|
2023-09-01 20:40:39 +02:00
|
|
|
UpdateLibraryMangasMutation,
|
|
|
|
|
UpdateLibraryMangasMutationVariables,
|
2023-09-01 20:33:35 +02:00
|
|
|
UpdateMangaCategoriesMutation,
|
|
|
|
|
UpdateMangaCategoriesMutationVariables,
|
|
|
|
|
UpdateMangaMutation,
|
|
|
|
|
UpdateMangaMutationVariables,
|
|
|
|
|
UpdateMangaPatchInput,
|
2023-10-04 22:34:32 +02:00
|
|
|
UpdaterSubscription,
|
|
|
|
|
UpdaterSubscriptionVariables,
|
2023-10-27 23:39:05 +02:00
|
|
|
UpdateServerSettingsMutation,
|
|
|
|
|
UpdateServerSettingsMutationVariables,
|
2023-09-25 23:32:26 +02:00
|
|
|
UpdateSourcePreferencesMutation,
|
|
|
|
|
UpdateSourcePreferencesMutationVariables,
|
2023-12-09 23:08:27 +01:00
|
|
|
UpdateWebuiMutation,
|
|
|
|
|
UpdateWebuiMutationVariables,
|
2023-10-04 01:17:10 +02:00
|
|
|
ValidateBackupQuery,
|
|
|
|
|
ValidateBackupQueryVariables,
|
2023-12-09 23:08:27 +01:00
|
|
|
WebuiUpdateSubscription,
|
|
|
|
|
ResetWebuiUpdateStatusMutation,
|
|
|
|
|
ResetWebuiUpdateStatusMutationVariables,
|
2023-12-13 02:05:03 +01:00
|
|
|
GetDownloadStatusQuery,
|
|
|
|
|
GetDownloadStatusQueryVariables,
|
2023-12-25 21:37:45 +01:00
|
|
|
GetMangasChapterIdsWithStateQuery,
|
|
|
|
|
GetMangasChapterIdsWithStateQueryVariables,
|
|
|
|
|
ChapterConditionInput,
|
|
|
|
|
UpdateMangasMutation,
|
|
|
|
|
UpdateMangasMutationVariables,
|
|
|
|
|
UpdateMangasCategoriesMutation,
|
|
|
|
|
UpdateMangasCategoriesMutationVariables,
|
|
|
|
|
UpdateMangaCategoriesPatchInput,
|
2024-01-01 22:40:39 +01:00
|
|
|
GetWebuiUpdateStatusQuery,
|
|
|
|
|
GetWebuiUpdateStatusQueryVariables,
|
2024-01-26 20:50:51 +01:00
|
|
|
GetMigratableSourcesQuery,
|
|
|
|
|
GetMigratableSourcesQueryVariables,
|
|
|
|
|
GetMigratableSourceMangasQuery,
|
|
|
|
|
GetMigratableSourceMangasQueryVariables,
|
|
|
|
|
GetMangaToMigrateQuery,
|
|
|
|
|
GetMangaToMigrateQueryVariables,
|
|
|
|
|
GetMangaToMigrateToFetchMutation,
|
|
|
|
|
GetMangaToMigrateToFetchMutationVariables,
|
2024-02-16 19:55:54 +01:00
|
|
|
GetTrackersQuery,
|
|
|
|
|
GetTrackersQueryVariables,
|
|
|
|
|
TrackerLogoutMutation,
|
|
|
|
|
TrackerLogoutMutationVariables,
|
|
|
|
|
TrackerLoginOauthMutation,
|
|
|
|
|
TrackerLoginOauthMutationVariables,
|
|
|
|
|
TrackerLoginCredentialsMutation,
|
|
|
|
|
TrackerLoginCredentialsMutationVariables,
|
2024-03-10 17:36:22 +01:00
|
|
|
TrackerSearchQuery,
|
|
|
|
|
TrackerSearchQueryVariables,
|
|
|
|
|
TrackerBindMutation,
|
|
|
|
|
TrackerBindMutationVariables,
|
2024-03-17 18:42:48 +01:00
|
|
|
TrackerUpdateBindMutation,
|
|
|
|
|
TrackerUpdateBindMutationVariables,
|
|
|
|
|
UpdateTrackInput,
|
2024-04-01 00:45:44 +02:00
|
|
|
TrackerUnbindMutation,
|
|
|
|
|
TrackerUnbindMutationVariables,
|
2024-04-01 02:06:35 +02:00
|
|
|
TrackerFetchBindMutation,
|
|
|
|
|
TrackerFetchBindMutationVariables,
|
2023-09-01 20:24:40 +02:00
|
|
|
} from '@/lib/graphql/generated/graphql.ts';
|
2023-10-16 00:05:51 +02:00
|
|
|
import { GET_GLOBAL_METADATAS } from '@/lib/graphql/queries/GlobalMetadataQuery.ts';
|
2023-09-01 20:24:40 +02:00
|
|
|
import { SET_GLOBAL_METADATA } from '@/lib/graphql/mutations/GlobalMetadataMutation.ts';
|
2024-01-01 22:40:39 +01:00
|
|
|
import {
|
|
|
|
|
CHECK_FOR_SERVER_UPDATES,
|
|
|
|
|
CHECK_FOR_WEBUI_UPDATE,
|
|
|
|
|
GET_ABOUT,
|
|
|
|
|
GET_WEBUI_UPDATE_STATUS,
|
|
|
|
|
} from '@/lib/graphql/queries/ServerInfoQuery.ts';
|
2023-10-16 00:05:51 +02:00
|
|
|
import { GET_EXTENSIONS } from '@/lib/graphql/queries/ExtensionQuery.ts';
|
2023-09-01 20:28:23 +02:00
|
|
|
import {
|
|
|
|
|
GET_EXTENSIONS_FETCH,
|
|
|
|
|
INSTALL_EXTERNAL_EXTENSION,
|
|
|
|
|
UPDATE_EXTENSION,
|
|
|
|
|
} from '@/lib/graphql/mutations/ExtensionMutation.ts';
|
2024-01-26 20:50:51 +01:00
|
|
|
import { GET_MIGRATABLE_SOURCES, GET_SOURCE, GET_SOURCES } from '@/lib/graphql/queries/SourceQuery.ts';
|
2023-09-08 00:44:01 +02:00
|
|
|
import {
|
|
|
|
|
GET_MANGA_FETCH,
|
2024-01-26 20:50:51 +01:00
|
|
|
GET_MANGA_TO_MIGRATE_TO_FETCH,
|
2023-09-08 00:44:01 +02:00
|
|
|
SET_MANGA_METADATA,
|
|
|
|
|
UPDATE_MANGA,
|
|
|
|
|
UPDATE_MANGA_CATEGORIES,
|
2023-12-25 21:37:45 +01:00
|
|
|
UPDATE_MANGAS,
|
|
|
|
|
UPDATE_MANGAS_CATEGORIES,
|
2023-09-08 00:44:01 +02:00
|
|
|
} from '@/lib/graphql/mutations/MangaMutation.ts';
|
2024-01-26 20:50:51 +01:00
|
|
|
import {
|
|
|
|
|
GET_MANGA,
|
|
|
|
|
GET_MANGA_TO_MIGRATE,
|
|
|
|
|
GET_MANGAS,
|
|
|
|
|
GET_MIGRATABLE_SOURCE_MANGAS,
|
|
|
|
|
} from '@/lib/graphql/queries/MangaQuery.ts';
|
2023-10-27 20:15:03 +02:00
|
|
|
import { GET_CATEGORIES, GET_CATEGORY_MANGAS } from '@/lib/graphql/queries/CategoryQuery.ts';
|
2023-09-25 23:32:26 +02:00
|
|
|
import { GET_SOURCE_MANGAS_FETCH, UPDATE_SOURCE_PREFERENCES } from '@/lib/graphql/mutations/SourceMutation.ts';
|
2023-09-01 20:40:24 +02:00
|
|
|
import {
|
|
|
|
|
CLEAR_DOWNLOADER,
|
|
|
|
|
DELETE_DOWNLOADED_CHAPTER,
|
|
|
|
|
DELETE_DOWNLOADED_CHAPTERS,
|
|
|
|
|
DEQUEUE_CHAPTER_DOWNLOAD,
|
|
|
|
|
DEQUEUE_CHAPTER_DOWNLOADS,
|
|
|
|
|
ENQUEUE_CHAPTER_DOWNLOAD,
|
|
|
|
|
ENQUEUE_CHAPTER_DOWNLOADS,
|
|
|
|
|
REORDER_CHAPTER_DOWNLOAD,
|
|
|
|
|
START_DOWNLOADER,
|
|
|
|
|
STOP_DOWNLOADER,
|
|
|
|
|
} from '@/lib/graphql/mutations/DownloaderMutation.ts';
|
2023-12-25 21:37:45 +01:00
|
|
|
import { GET_CHAPTERS, GET_MANGAS_CHAPTER_IDS_WITH_STATE } from '@/lib/graphql/queries/ChapterQuery.ts';
|
2023-09-30 16:55:35 +02:00
|
|
|
import {
|
|
|
|
|
GET_CHAPTER_PAGES_FETCH,
|
|
|
|
|
GET_MANGA_CHAPTERS_FETCH,
|
|
|
|
|
SET_CHAPTER_METADATA,
|
|
|
|
|
UPDATE_CHAPTER,
|
|
|
|
|
UPDATE_CHAPTERS,
|
|
|
|
|
} from '@/lib/graphql/mutations/ChapterMutation.ts';
|
2023-09-01 20:39:30 +02:00
|
|
|
import {
|
|
|
|
|
CREATE_CATEGORY,
|
|
|
|
|
DELETE_CATEGORY,
|
|
|
|
|
SET_CATEGORY_METADATA,
|
|
|
|
|
UPDATE_CATEGORY,
|
|
|
|
|
UPDATE_CATEGORY_ORDER,
|
|
|
|
|
} from '@/lib/graphql/mutations/CategoryMutation.ts';
|
2023-09-01 20:40:39 +02:00
|
|
|
import {
|
|
|
|
|
STOP_UPDATER,
|
|
|
|
|
UPDATE_CATEGORY_MANGAS,
|
|
|
|
|
UPDATE_LIBRARY_MANGAS,
|
|
|
|
|
} from '@/lib/graphql/mutations/UpdaterMutation.ts';
|
2023-11-19 22:43:29 +01:00
|
|
|
import { GET_LAST_UPDATE_TIMESTAMP, GET_UPDATE_STATUS } from '@/lib/graphql/queries/UpdaterQuery.ts';
|
2023-09-12 02:36:11 +02:00
|
|
|
import { CustomCache } from '@/lib/requests/CustomCache.ts';
|
2023-10-04 01:17:10 +02:00
|
|
|
import { RESTORE_BACKUP } from '@/lib/graphql/mutations/BackupMutation.ts';
|
2023-10-29 01:49:27 +02:00
|
|
|
import { GET_RESTORE_STATUS, VALIDATE_BACKUP } from '@/lib/graphql/queries/BackupQuery.ts';
|
2023-10-04 22:34:32 +02:00
|
|
|
import { DOWNLOAD_STATUS_SUBSCRIPTION } from '@/lib/graphql/subscriptions/DownloaderSubscription.ts';
|
|
|
|
|
import { UPDATER_SUBSCRIPTION } from '@/lib/graphql/subscriptions/UpdaterSubscription.ts';
|
2023-10-27 23:39:05 +02:00
|
|
|
import { GET_SERVER_SETTINGS } from '@/lib/graphql/queries/SettingsQuery.ts';
|
|
|
|
|
import { UPDATE_SERVER_SETTINGS } from '@/lib/graphql/mutations/SettingsMutation.ts';
|
2024-04-27 22:28:55 +02:00
|
|
|
import {
|
|
|
|
|
BASE_MANGA_FIELDS,
|
|
|
|
|
FULL_DOWNLOAD_STATUS,
|
|
|
|
|
FULL_EXTENSION_FIELDS,
|
|
|
|
|
GLOBAL_METADATA,
|
|
|
|
|
} from '@/lib/graphql/Fragments.ts';
|
2023-12-09 14:16:52 +01:00
|
|
|
import { CLEAR_SERVER_CACHE } from '@/lib/graphql/mutations/ImageMutation.ts';
|
2023-12-09 23:08:27 +01:00
|
|
|
import { RESET_WEBUI_UPDATE_STATUS, UPDATE_WEBUI } from '@/lib/graphql/mutations/ServerInfoMutation.ts';
|
|
|
|
|
import { WEBUI_UPDATE_SUBSCRIPTION } from '@/lib/graphql/subscriptions/ServerInfoSubscription.ts';
|
2023-12-13 02:05:03 +01:00
|
|
|
import { GET_DOWNLOAD_STATUS } from '@/lib/graphql/queries/DownloaderQuery.ts';
|
2023-12-31 01:42:54 +01:00
|
|
|
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
2024-03-24 19:08:36 +01:00
|
|
|
import { Queue, QueuePriority } from '@/lib/Queue.ts';
|
2024-03-10 17:36:22 +01:00
|
|
|
import { GET_TRACKERS, TRACKER_SEARCH } from '@/lib/graphql/queries/TrackerQuery.ts';
|
2024-02-16 19:55:54 +01:00
|
|
|
import {
|
2024-03-10 17:36:22 +01:00
|
|
|
TRACKER_BIND,
|
2024-04-01 02:06:35 +02:00
|
|
|
TRACKER_FETCH_BIND,
|
2024-02-16 19:55:54 +01:00
|
|
|
TRACKER_LOGIN_CREDENTIALS,
|
|
|
|
|
TRACKER_LOGIN_OAUTH,
|
|
|
|
|
TRACKER_LOGOUT,
|
2024-04-01 00:45:44 +02:00
|
|
|
TRACKER_UNBIND,
|
2024-03-17 18:42:48 +01:00
|
|
|
TRACKER_UPDATE_BIND,
|
2024-02-16 19:55:54 +01:00
|
|
|
} from '@/lib/graphql/mutations/TrackerMutation.ts';
|
2024-03-28 22:40:55 +01:00
|
|
|
import { ControlledPromise } from '@/lib/ControlledPromise.ts';
|
2024-04-20 23:51:47 +02:00
|
|
|
import { MetadataMigrationSettings, TManga } from '@/typings.ts';
|
2023-05-18 13:25:19 +02:00
|
|
|
|
2023-09-01 20:21:59 +02:00
|
|
|
enum GQLMethod {
|
2023-09-30 16:55:35 +02:00
|
|
|
QUERY = 'QUERY',
|
2023-09-01 20:21:59 +02:00
|
|
|
USE_QUERY = 'USE_QUERY',
|
|
|
|
|
USE_MUTATION = 'USE_MUTATION',
|
|
|
|
|
MUTATION = 'MUTATION',
|
2023-10-04 22:34:32 +02:00
|
|
|
USE_SUBSCRIPTION = 'USE_SUBSCRIPTION',
|
2023-09-01 20:21:59 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-02 16:58:32 +02:00
|
|
|
type CustomApolloOptions = {
|
|
|
|
|
/**
|
|
|
|
|
* This is a workaround for an apollo bug (?).
|
|
|
|
|
*
|
|
|
|
|
* A new abort signal gets passed on every hook call.
|
|
|
|
|
* This causes the passed arguments to change (due to updating the "context" option, which is only relevant for the actual request),
|
|
|
|
|
* which - I assume - results in apollo to handle this as a completely new hook call.
|
|
|
|
|
* Due to this, when e.g. calling "fetchMore", "loading" and "networkStatus" do not get updated when enabling "notifyOnNetworkStatusChange".
|
|
|
|
|
*
|
2023-11-11 23:42:58 +01:00
|
|
|
* It also causes apollo to spam requests in case of request failures on every rerender.
|
|
|
|
|
*
|
|
|
|
|
* Instead of adding the abort signal by default, it has to be added manually which will cause these stated issues (and potentially more?)
|
2023-10-02 16:58:32 +02:00
|
|
|
*/
|
2023-11-11 23:42:58 +01:00
|
|
|
addAbortSignal?: boolean;
|
2023-10-02 16:58:32 +02:00
|
|
|
};
|
2023-10-04 22:34:32 +02:00
|
|
|
type QueryOptions<Variables extends OperationVariables = OperationVariables, Data = any> = Partial<
|
|
|
|
|
ApolloQueryOptions<Variables, Data>
|
2023-10-02 16:58:32 +02:00
|
|
|
> &
|
|
|
|
|
CustomApolloOptions;
|
2023-10-04 22:34:32 +02:00
|
|
|
type QueryHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
|
|
|
|
|
ApolloQueryHookOptions<Data, Variables>
|
2023-10-02 16:58:32 +02:00
|
|
|
> &
|
|
|
|
|
CustomApolloOptions;
|
|
|
|
|
type MutationHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
|
|
|
|
|
ApolloMutationHookOptions<Data, Variables>
|
|
|
|
|
> &
|
|
|
|
|
CustomApolloOptions;
|
|
|
|
|
type MutationOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
|
|
|
|
|
ApolloMutationOptions<Data, Variables>
|
|
|
|
|
> &
|
|
|
|
|
CustomApolloOptions;
|
2023-10-04 22:34:32 +02:00
|
|
|
type ApolloPaginatedMutationOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
|
|
|
|
|
MutationHookOptions<Data, Variables>
|
|
|
|
|
> & { skipRequest?: boolean };
|
|
|
|
|
type SubscriptionHookOptions<Data = any, Variables extends OperationVariables = OperationVariables> = Partial<
|
|
|
|
|
ApolloSubscriptionHookOptions<Data, Variables>
|
|
|
|
|
> &
|
2023-11-11 23:42:58 +01:00
|
|
|
Omit<CustomApolloOptions, 'addAbortSignal'> & { addAbortSignal?: never };
|
2023-09-12 02:36:11 +02:00
|
|
|
|
2023-05-23 13:27:38 +02:00
|
|
|
type AbortableRequest = { abortRequest: AbortController['abort'] };
|
|
|
|
|
|
2024-03-28 22:40:55 +01:00
|
|
|
type ImageRequest = { response: Promise<string>; cleanup: () => void } & AbortableRequest;
|
|
|
|
|
|
2023-09-30 16:55:35 +02:00
|
|
|
export type AbortabaleApolloQueryResponse<Data = any> = {
|
|
|
|
|
response: Promise<ApolloQueryResult<Data>>;
|
|
|
|
|
} & AbortableRequest;
|
2023-09-12 02:36:11 +02:00
|
|
|
export type AbortableApolloUseQueryResponse<
|
2023-09-01 20:21:59 +02:00
|
|
|
Data = any,
|
|
|
|
|
Variables extends OperationVariables = OperationVariables,
|
|
|
|
|
> = QueryResult<Data, Variables> & AbortableRequest;
|
2023-09-12 02:36:11 +02:00
|
|
|
export type AbortableApolloUseMutationResponse<
|
|
|
|
|
Data = any,
|
|
|
|
|
Variables extends OperationVariables = OperationVariables,
|
|
|
|
|
> = [MutationTuple<Data, Variables>[0], MutationTuple<Data, Variables>[1] & AbortableRequest];
|
|
|
|
|
export type AbortableApolloUseMutationPaginatedResponse<
|
2023-09-08 00:06:24 +02:00
|
|
|
Data = any,
|
|
|
|
|
Variables extends OperationVariables = OperationVariables,
|
|
|
|
|
> = [
|
|
|
|
|
(page: number) => Promise<FetchResult<Data>>,
|
2023-09-12 02:36:11 +02:00
|
|
|
(Omit<MutationTuple<Data, Variables>[1], 'loading'> &
|
|
|
|
|
AbortableRequest & {
|
|
|
|
|
size: number;
|
|
|
|
|
/**
|
|
|
|
|
* Indicates whether any request is currently active.
|
|
|
|
|
* In case only "isLoading" is true, it means that it's the initial request
|
|
|
|
|
*/
|
|
|
|
|
isLoading: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* Indicates if a next page is being fetched, which is not part of the initial pages
|
|
|
|
|
*/
|
|
|
|
|
isLoadingMore: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* Indicates if the cached pages are currently getting revalidated
|
|
|
|
|
*/
|
|
|
|
|
isValidating: boolean;
|
|
|
|
|
})[],
|
2023-09-08 00:06:24 +02:00
|
|
|
];
|
2023-09-12 02:36:11 +02:00
|
|
|
export type AbortableApolloMutationResponse<Data = any> = { response: Promise<FetchResult<Data>> } & AbortableRequest;
|
2023-09-01 20:21:59 +02:00
|
|
|
|
2023-11-05 22:37:28 +01:00
|
|
|
const EXTENSION_LIST_CACHE_KEY = 'useExtensionListFetch';
|
|
|
|
|
|
2023-11-11 23:43:22 +01:00
|
|
|
const CACHE_INITIAL_PAGES_FETCHING_KEY = 'GET_SOURCE_MANGAS_FETCH_FETCHING_INITIAL_PAGES';
|
|
|
|
|
const CACHE_PAGES_KEY = 'GET_SOURCE_MANGAS_FETCH_PAGES';
|
|
|
|
|
const CACHE_RESULTS_KEY = 'GET_SOURCE_MANGAS_FETCH';
|
|
|
|
|
|
|
|
|
|
export const SPECIAL_ED_SOURCES = {
|
|
|
|
|
REVALIDATION: [
|
|
|
|
|
'57122881048805941', // e-hentai
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-13 02:05:03 +01:00
|
|
|
// TODO - extract logic to reduce the size of this file... grew waaaaaaaaaaaaay too big peepoFat
|
2023-10-16 00:05:51 +02:00
|
|
|
// TODO - correctly update cache after all mutations instead of refetching queries
|
2023-05-18 13:25:19 +02:00
|
|
|
export class RequestManager {
|
2023-06-04 00:50:58 +02:00
|
|
|
public static readonly API_VERSION = '/api/v1/';
|
2023-05-18 13:25:19 +02:00
|
|
|
|
2023-12-09 23:08:27 +01:00
|
|
|
public readonly graphQLClient = new GraphQLClient();
|
2023-09-01 20:21:59 +02:00
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
private readonly restClient: RestClient = new RestClient();
|
|
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
private readonly cache = new CustomCache();
|
|
|
|
|
|
2024-03-24 19:08:36 +01:00
|
|
|
private readonly imageQueue = new Queue(5);
|
2024-03-05 02:11:40 +01:00
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public getClient(): IRestClient {
|
|
|
|
|
return this.restClient;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 02:07:05 +01:00
|
|
|
public updateClient(config: RequestInit): void {
|
2023-05-18 13:25:19 +02:00
|
|
|
this.restClient.updateConfig(config);
|
2023-10-04 20:50:11 +02:00
|
|
|
this.graphQLClient.updateConfig();
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-10 01:23:08 +02:00
|
|
|
public reset(): void {
|
|
|
|
|
this.graphQLClient.client.resetStore();
|
|
|
|
|
this.cache.clear();
|
|
|
|
|
this.imageQueue.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public getBaseUrl(): string {
|
2024-03-05 02:07:05 +01:00
|
|
|
return this.restClient.getBaseUrl();
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getValidUrlFor(endpoint: string, apiVersion: string = RequestManager.API_VERSION): string {
|
|
|
|
|
return `${this.getBaseUrl()}${apiVersion}${endpoint}`;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-11 23:43:22 +01:00
|
|
|
public clearBrowseCacheFor(sourceId: string) {
|
|
|
|
|
const cacheKeys = this.cache.getMatchingKeys(
|
|
|
|
|
new RegExp(`${CACHE_INITIAL_PAGES_FETCHING_KEY}|${CACHE_PAGES_KEY}|${CACHE_RESULTS_KEY}.*${sourceId}`),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.cache.clearFor(...cacheKeys);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 23:22:25 +01:00
|
|
|
public clearExtensionCache() {
|
|
|
|
|
this.cache.clearFor(this.cache.getKeyFor(EXTENSION_LIST_CACHE_KEY, undefined));
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
private createAbortController(): { signal: AbortSignal } & AbortableRequest {
|
|
|
|
|
const abortController = new AbortController();
|
|
|
|
|
const abortRequest = (reason?: any): void => {
|
|
|
|
|
if (!abortController.signal.aborted) {
|
|
|
|
|
abortController.abort(reason);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return { signal: abortController.signal, abortRequest };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createPaginatedResult<Result extends AbortableApolloUseMutationPaginatedResponse[1][number]>(
|
|
|
|
|
result: Partial<Result> | undefined | null,
|
|
|
|
|
defaultPage: number,
|
|
|
|
|
page?: number,
|
|
|
|
|
): Result {
|
|
|
|
|
const isLoading = !result?.error && (result?.isLoading || !result?.called);
|
|
|
|
|
const size = page ?? result?.size ?? defaultPage;
|
|
|
|
|
return {
|
|
|
|
|
client: this.graphQLClient.client,
|
|
|
|
|
abortRequest: () => {},
|
|
|
|
|
reset: () => {},
|
|
|
|
|
called: false,
|
|
|
|
|
data: undefined,
|
|
|
|
|
error: undefined,
|
|
|
|
|
size,
|
|
|
|
|
isLoading,
|
|
|
|
|
isLoadingMore: isLoading && size > 1,
|
|
|
|
|
isValidating: !!result?.isValidating,
|
|
|
|
|
...result,
|
|
|
|
|
} as Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async revalidatePage<Data = any, Variables extends OperationVariables = OperationVariables>(
|
2023-11-11 23:43:22 +01:00
|
|
|
sourceId: string,
|
2023-09-12 02:36:11 +02:00
|
|
|
cacheResultsKey: string,
|
|
|
|
|
cachePagesKey: string,
|
|
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
options: ApolloPaginatedMutationOptions<Data, Variables> | undefined,
|
|
|
|
|
checkIfCachedPageIsInvalid: (
|
|
|
|
|
cachedResult: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number] | undefined,
|
|
|
|
|
revalidatedResult: FetchResult<Data>,
|
|
|
|
|
) => boolean,
|
|
|
|
|
hasNextPage: (revalidatedResult: FetchResult<Data>) => boolean,
|
|
|
|
|
pageToRevalidate: number,
|
|
|
|
|
maxPage: number,
|
|
|
|
|
signal: AbortSignal,
|
|
|
|
|
): Promise<void> {
|
2023-11-11 23:43:22 +01:00
|
|
|
if (SPECIAL_ED_SOURCES.REVALIDATION.includes(sourceId)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-23 23:34:20 +01:00
|
|
|
const isFirstPage = pageToRevalidate === 1;
|
|
|
|
|
const isTtlReached =
|
|
|
|
|
Date.now() - (this.cache.getFetchTimestampFor(cacheResultsKey, getVariablesFor(pageToRevalidate)) ?? 0) >=
|
|
|
|
|
1000 * 60 * 5;
|
|
|
|
|
|
|
|
|
|
if (isFirstPage && !isTtlReached) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
const { response: revalidationRequest } = this.doRequest(
|
2023-09-12 02:36:11 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
GET_SOURCE_MANGAS_FETCH,
|
|
|
|
|
getVariablesFor(pageToRevalidate),
|
|
|
|
|
{
|
|
|
|
|
...options,
|
|
|
|
|
context: { fetchOptions: { signal } },
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const revalidationResponse = await revalidationRequest;
|
|
|
|
|
const cachedPageData = this.cache.getResponseFor<
|
|
|
|
|
AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]
|
|
|
|
|
>(cacheResultsKey, getVariablesFor(pageToRevalidate));
|
|
|
|
|
const isCachedPageInvalid = checkIfCachedPageIsInvalid(cachedPageData, revalidationResponse);
|
2024-03-23 23:34:20 +01:00
|
|
|
|
|
|
|
|
this.cache.cacheResponse(cacheResultsKey, getVariablesFor(pageToRevalidate), revalidationResponse);
|
2023-09-12 02:36:11 +02:00
|
|
|
|
|
|
|
|
if (!hasNextPage(revalidationResponse)) {
|
|
|
|
|
const currentCachedPages = this.cache.getResponseFor<Set<number>>(cachePagesKey, getVariablesFor(0))!;
|
|
|
|
|
this.cache.cacheResponse(
|
|
|
|
|
cachePagesKey,
|
|
|
|
|
getVariablesFor(0),
|
|
|
|
|
[...currentCachedPages].filter((cachedPage) => cachedPage <= pageToRevalidate),
|
|
|
|
|
);
|
|
|
|
|
[...currentCachedPages]
|
|
|
|
|
.filter((cachedPage) => cachedPage > pageToRevalidate)
|
|
|
|
|
.forEach((cachedPage) =>
|
|
|
|
|
this.cache.cacheResponse(cacheResultsKey, getVariablesFor(cachedPage), undefined),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isCachedPageInvalid && pageToRevalidate < maxPage) {
|
|
|
|
|
await this.revalidatePage(
|
2023-11-11 23:43:22 +01:00
|
|
|
sourceId,
|
2023-09-12 02:36:11 +02:00
|
|
|
cacheResultsKey,
|
|
|
|
|
cachePagesKey,
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
options,
|
|
|
|
|
checkIfCachedPageIsInvalid,
|
|
|
|
|
hasNextPage,
|
|
|
|
|
pageToRevalidate + 1,
|
|
|
|
|
maxPage,
|
|
|
|
|
signal,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async revalidatePages<Variables extends OperationVariables = OperationVariables>(
|
|
|
|
|
activeRevalidationRef:
|
|
|
|
|
| [ForInput: Variables, Request: Promise<unknown>, AbortRequest: AbortableRequest['abortRequest']]
|
|
|
|
|
| null,
|
|
|
|
|
setRevalidationDone: (isDone: boolean) => void,
|
|
|
|
|
setActiveRevalidation: (
|
|
|
|
|
activeRevalidation:
|
|
|
|
|
| [ForInput: Variables, Request: Promise<unknown>, AbortRequest: AbortableRequest['abortRequest']]
|
|
|
|
|
| null,
|
|
|
|
|
) => void,
|
|
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
setValidating: (isValidating: boolean) => void,
|
|
|
|
|
revalidatePage: (pageToRevalidate: number, maxPage: number, signal: AbortSignal) => Promise<void>,
|
|
|
|
|
maxPage: number,
|
|
|
|
|
abortRequest: AbortableRequest['abortRequest'],
|
|
|
|
|
signal: AbortSignal,
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
setRevalidationDone(true);
|
|
|
|
|
|
|
|
|
|
const [currRevVars, currRevPromise, currRevAbortRequest] = activeRevalidationRef ?? [];
|
|
|
|
|
|
|
|
|
|
const isActiveRevalidationForInput = JSON.stringify(currRevVars) === JSON.stringify(getVariablesFor(0));
|
|
|
|
|
|
|
|
|
|
setValidating(true);
|
|
|
|
|
|
|
|
|
|
if (!isActiveRevalidationForInput) {
|
|
|
|
|
currRevAbortRequest?.(new Error('Abort revalidation for different input'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let revalidationPromise = currRevPromise;
|
|
|
|
|
if (!isActiveRevalidationForInput) {
|
|
|
|
|
revalidationPromise = revalidatePage(1, maxPage, signal);
|
|
|
|
|
setActiveRevalidation([getVariablesFor(0), revalidationPromise, abortRequest]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await revalidationPromise;
|
|
|
|
|
setActiveRevalidation(null);
|
|
|
|
|
} catch (e) {
|
2023-12-31 01:42:54 +01:00
|
|
|
defaultPromiseErrorHandler(`RequestManager..revalidatePages(${getVariablesFor(0)})`)(e);
|
2023-09-12 02:36:11 +02:00
|
|
|
} finally {
|
|
|
|
|
setValidating(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async fetchPaginatedMutationPage<
|
|
|
|
|
Data = any,
|
|
|
|
|
Variables extends OperationVariables = OperationVariables,
|
|
|
|
|
ResultIdInfo extends Record<string, any> = any,
|
|
|
|
|
>(
|
|
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
setAbortRequest: (abortRequest: AbortableRequest['abortRequest']) => void,
|
|
|
|
|
getResultIdInfo: () => ResultIdInfo,
|
|
|
|
|
createPaginatedResult: (
|
|
|
|
|
result: Partial<AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]>,
|
|
|
|
|
) => AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number],
|
|
|
|
|
setResult: (
|
|
|
|
|
result: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number] & ResultIdInfo,
|
|
|
|
|
) => void,
|
|
|
|
|
revalidate: (
|
|
|
|
|
maxPage: number,
|
|
|
|
|
abortRequest: AbortableRequest['abortRequest'],
|
|
|
|
|
signal: AbortSignal,
|
|
|
|
|
) => Promise<void>,
|
|
|
|
|
options: ApolloPaginatedMutationOptions<Data, Variables> | undefined,
|
|
|
|
|
documentNode: DocumentNode,
|
|
|
|
|
cachePagesKey: string,
|
|
|
|
|
cacheResultsKey: string,
|
|
|
|
|
cachedPages: Set<number>,
|
|
|
|
|
newPage: number,
|
|
|
|
|
): Promise<FetchResult<Data>> {
|
|
|
|
|
const basePaginatedResult: Partial<AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]> = {
|
|
|
|
|
size: newPage,
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isLoadingMore: false,
|
|
|
|
|
called: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let response: FetchResult<Data> = {};
|
|
|
|
|
try {
|
|
|
|
|
const { signal, abortRequest } = this.createAbortController();
|
|
|
|
|
setAbortRequest(abortRequest);
|
|
|
|
|
|
|
|
|
|
setResult({
|
|
|
|
|
...getResultIdInfo(),
|
|
|
|
|
...createPaginatedResult({ isLoading: true, abortRequest, size: newPage, called: true }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (newPage !== 1 && cachedPages.size) {
|
|
|
|
|
await revalidate(newPage, abortRequest, signal);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
const { response: request } = this.doRequest<Data, Variables>(
|
2023-09-12 02:36:11 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
documentNode,
|
|
|
|
|
getVariablesFor(newPage),
|
|
|
|
|
{ ...options, context: { fetchOptions: { signal } } },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
response = await request;
|
|
|
|
|
|
|
|
|
|
basePaginatedResult.data = response.data;
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
if (error instanceof ApolloError) {
|
|
|
|
|
basePaginatedResult.error = error;
|
|
|
|
|
} else {
|
|
|
|
|
basePaginatedResult.error = new ApolloError({
|
|
|
|
|
errorMessage: error?.message ?? error.toString(),
|
|
|
|
|
extraInfo: error,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fetchPaginatedResult = {
|
|
|
|
|
...getResultIdInfo(),
|
|
|
|
|
...createPaginatedResult(basePaginatedResult),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setResult(fetchPaginatedResult);
|
|
|
|
|
|
|
|
|
|
const shouldCacheResult = !fetchPaginatedResult.error;
|
|
|
|
|
if (shouldCacheResult) {
|
|
|
|
|
const currentCachedPages = this.cache.getResponseFor<Set<number>>(cachePagesKey, getVariablesFor(0)) ?? [];
|
|
|
|
|
this.cache.cacheResponse(cachePagesKey, getVariablesFor(0), new Set([...currentCachedPages, newPage]));
|
|
|
|
|
this.cache.cacheResponse(cacheResultsKey, getVariablesFor(newPage), fetchPaginatedResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fetchInitialPages<Data = any, Variables extends OperationVariables = OperationVariables>(
|
|
|
|
|
options: ApolloPaginatedMutationOptions<Data, Variables> | undefined,
|
|
|
|
|
areFetchingInitialPages: boolean,
|
|
|
|
|
areInitialPagesFetched: boolean,
|
|
|
|
|
setRevalidationDone: (isDone: boolean) => void,
|
2023-11-11 23:42:58 +01:00
|
|
|
cacheFetchingInitialPagesKey: string,
|
2023-09-12 02:36:11 +02:00
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
initialPages: number,
|
|
|
|
|
fetchPage: (page: number) => Promise<FetchResult<Data>>,
|
|
|
|
|
hasNextPage: (result: FetchResult<Data>) => boolean,
|
|
|
|
|
): void {
|
2023-11-11 23:42:58 +01:00
|
|
|
useEffect(() => {
|
|
|
|
|
const shouldFetchInitialPages =
|
|
|
|
|
!options?.skipRequest && !areFetchingInitialPages && !areInitialPagesFetched;
|
|
|
|
|
if (!shouldFetchInitialPages) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
setRevalidationDone(true);
|
2023-11-11 23:42:58 +01:00
|
|
|
this.cache.cacheResponse(cacheFetchingInitialPagesKey, getVariablesFor(0), true);
|
2023-09-12 02:36:11 +02:00
|
|
|
|
|
|
|
|
const loadInitialPages = async (initialPage: number) => {
|
|
|
|
|
const areAllPagesFetched = initialPage > initialPages;
|
|
|
|
|
if (areAllPagesFetched) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const pageResult = await fetchPage(initialPage);
|
|
|
|
|
|
|
|
|
|
if (hasNextPage(pageResult)) {
|
|
|
|
|
await loadInitialPages(initialPage + 1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-11 23:42:58 +01:00
|
|
|
loadInitialPages(1).finally(() =>
|
|
|
|
|
this.cache.cacheResponse(cacheFetchingInitialPagesKey, getVariablesFor(0), false),
|
|
|
|
|
);
|
|
|
|
|
}, [!options?.skipRequest, !areFetchingInitialPages, !areInitialPagesFetched]);
|
2023-09-12 02:36:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private returnPaginatedMutationResult<Data = any, Variables extends OperationVariables = OperationVariables>(
|
|
|
|
|
areInitialPagesFetched: boolean,
|
|
|
|
|
cachedResults: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number][],
|
|
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
paginatedResult: AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number],
|
|
|
|
|
fetchPage: (page: number) => Promise<FetchResult<Data>>,
|
|
|
|
|
hasCachedResult: boolean,
|
|
|
|
|
createPaginatedResult: (
|
|
|
|
|
result: Partial<AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number]>,
|
|
|
|
|
) => AbortableApolloUseMutationPaginatedResponse<Data, Variables>[1][number],
|
|
|
|
|
): AbortableApolloUseMutationPaginatedResponse<Data, Variables> {
|
|
|
|
|
const doCachedResultsExist = areInitialPagesFetched && cachedResults.length;
|
|
|
|
|
if (!doCachedResultsExist) {
|
|
|
|
|
return [fetchPage, [paginatedResult]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const areAllPagesCached = doCachedResultsExist && hasCachedResult;
|
|
|
|
|
if (!areAllPagesCached) {
|
|
|
|
|
return [fetchPage, [...cachedResults, paginatedResult]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
fetchPage,
|
|
|
|
|
[
|
|
|
|
|
...cachedResults.slice(0, cachedResults.length - 1),
|
|
|
|
|
createPaginatedResult({
|
|
|
|
|
...cachedResults[cachedResults.length - 1],
|
|
|
|
|
isValidating: paginatedResult.isValidating,
|
|
|
|
|
}),
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private revalidateInitialPages<Variables extends OperationVariables = OperationVariables>(
|
|
|
|
|
isRevalidationDone: boolean,
|
|
|
|
|
cachedResultsLength: number,
|
|
|
|
|
cachedPages: Set<number>,
|
|
|
|
|
setRevalidationDone: (isDone: boolean) => void,
|
|
|
|
|
getVariablesFor: (page: number) => Variables,
|
|
|
|
|
triggerRerender: () => void,
|
|
|
|
|
revalidate: (
|
|
|
|
|
maxPage: number,
|
|
|
|
|
abortRequest: AbortableRequest['abortRequest'],
|
|
|
|
|
signal: AbortSignal,
|
|
|
|
|
) => Promise<void>,
|
|
|
|
|
): void {
|
|
|
|
|
const isMountedRef = useRef(false);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const isRevalidationRequired = isMountedRef.current && cachedResultsLength;
|
|
|
|
|
if (!isRevalidationRequired) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setRevalidationDone(false);
|
|
|
|
|
triggerRerender();
|
|
|
|
|
}, [JSON.stringify(getVariablesFor(0))]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const shouldRevalidateData = isMountedRef.current && !isRevalidationDone && cachedResultsLength;
|
|
|
|
|
if (shouldRevalidateData) {
|
|
|
|
|
setRevalidationDone(true);
|
|
|
|
|
|
|
|
|
|
const { signal, abortRequest } = this.createAbortController();
|
|
|
|
|
revalidate(Math.max(...cachedPages), abortRequest, signal);
|
|
|
|
|
}
|
|
|
|
|
}, [isMountedRef.current, isRevalidationDone]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
isMountedRef.current = true;
|
|
|
|
|
}, []);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public getValidImgUrlFor(imageUrl: string, apiVersion: string = ''): string {
|
|
|
|
|
// server provided image urls already contain the api version
|
2024-03-22 03:33:09 +01:00
|
|
|
return `${this.getValidUrlFor(imageUrl, apiVersion)}`;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-28 22:40:55 +01:00
|
|
|
private fetchImageViaTag(url: string, priority?: QueuePriority): ImageRequest {
|
|
|
|
|
const imgRequest = new ControlledPromise<string>();
|
2024-04-26 17:29:58 +02:00
|
|
|
imgRequest.promise.catch(() => {});
|
2024-03-28 22:40:55 +01:00
|
|
|
|
|
|
|
|
const img = new Image();
|
|
|
|
|
const abortRequest = (reason?: any) => {
|
|
|
|
|
img.src = '';
|
|
|
|
|
img.onload = null;
|
|
|
|
|
img.onerror = null;
|
|
|
|
|
img.onabort = null;
|
|
|
|
|
imgRequest.reject(reason);
|
|
|
|
|
};
|
|
|
|
|
|
2024-05-06 02:32:31 +02:00
|
|
|
const { key, promise: response } = this.imageQueue.enqueue(
|
2024-03-28 22:40:55 +01:00
|
|
|
url,
|
|
|
|
|
async () => {
|
|
|
|
|
// throws error in case request was already aborted
|
|
|
|
|
await Promise.race([imgRequest.promise, Promise.resolve()]);
|
|
|
|
|
|
|
|
|
|
img.src = url;
|
|
|
|
|
|
|
|
|
|
img.onload = () => imgRequest.resolve(url);
|
|
|
|
|
img.onerror = (error) => imgRequest.reject(error);
|
|
|
|
|
img.onabort = (error) => imgRequest.reject(error);
|
|
|
|
|
|
|
|
|
|
return imgRequest.promise;
|
|
|
|
|
},
|
|
|
|
|
priority,
|
|
|
|
|
);
|
|
|
|
|
|
2024-05-06 02:32:31 +02:00
|
|
|
return {
|
|
|
|
|
response,
|
|
|
|
|
abortRequest: (reason?: any) => {
|
|
|
|
|
if (this.imageQueue.isProcessing(key)) {
|
|
|
|
|
// prevent aborting image requests that are already in progress
|
|
|
|
|
// e.g. for source image requests, ongoing requests are already handled by the server and aborting them
|
|
|
|
|
// will just cause new source image requests to be sent to the server, which then will cause the server
|
|
|
|
|
// to become really slow for image requests to the same source
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
abortRequest(reason);
|
|
|
|
|
},
|
|
|
|
|
cleanup: () => {},
|
|
|
|
|
};
|
2024-03-28 22:40:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-01 18:27:46 +01:00
|
|
|
/**
|
|
|
|
|
* After the image has been handled, {@see URL#revokeObjectURL} has to be called.
|
|
|
|
|
*
|
|
|
|
|
* @example
|
|
|
|
|
*
|
|
|
|
|
* const imageRequest = requestManager.requestImage("someUrl");
|
|
|
|
|
* const imageUrl = await imageRequest.response
|
|
|
|
|
*
|
|
|
|
|
* const img = new Image();
|
2024-03-28 22:40:55 +01:00
|
|
|
* img.onLoad = () => imageRequest.cleanup();
|
2024-03-01 18:27:46 +01:00
|
|
|
* img.src = imageUrl;
|
|
|
|
|
*
|
|
|
|
|
*/
|
2024-03-28 22:40:55 +01:00
|
|
|
private fetchImageViaFetchApi(url: string, priority?: QueuePriority): ImageRequest {
|
|
|
|
|
let objectUrl: string = '';
|
2024-03-01 01:17:23 +01:00
|
|
|
const { abortRequest, signal } = this.createAbortController();
|
2024-05-06 02:32:31 +02:00
|
|
|
const { key, promise: response } = this.imageQueue.enqueue(
|
2024-03-24 19:08:36 +01:00
|
|
|
url,
|
|
|
|
|
() =>
|
|
|
|
|
this.restClient
|
|
|
|
|
.fetcher(url, {
|
|
|
|
|
checkResponseIsJson: false,
|
|
|
|
|
config: {
|
|
|
|
|
signal,
|
|
|
|
|
// @ts-ignore - typing has not been updated yet
|
|
|
|
|
priority: 'low',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
.then((data) => data.blob())
|
2024-03-28 22:40:55 +01:00
|
|
|
.then((data) => URL.createObjectURL(data))
|
|
|
|
|
.then((imageUrl) => {
|
|
|
|
|
objectUrl = imageUrl;
|
|
|
|
|
return imageUrl;
|
|
|
|
|
}),
|
2024-03-24 19:08:36 +01:00
|
|
|
priority,
|
2024-03-05 02:11:40 +01:00
|
|
|
);
|
2024-03-01 01:17:23 +01:00
|
|
|
|
2024-05-06 02:32:31 +02:00
|
|
|
return {
|
|
|
|
|
response,
|
|
|
|
|
abortRequest: (reason?: any) => {
|
|
|
|
|
if (this.imageQueue.isProcessing(key)) {
|
|
|
|
|
// prevent aborting image requests that are already in progress
|
|
|
|
|
// e.g. for source image requests, ongoing requests are already handled by the server and aborting them
|
|
|
|
|
// will just cause new source image requests to be sent to the server, which then will cause the server
|
|
|
|
|
// to become really slow for image requests to the same source
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
abortRequest(reason);
|
|
|
|
|
},
|
|
|
|
|
cleanup: () => URL.revokeObjectURL(objectUrl),
|
|
|
|
|
};
|
2024-03-28 22:40:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Make sure to call "cleanup" once the image is not needed anymore (only required if fetched via "fetch api")
|
|
|
|
|
*/
|
2024-04-10 01:22:47 +02:00
|
|
|
public requestImage(url: string, priority?: QueuePriority, useFetchApi: boolean = false): ImageRequest {
|
2024-03-28 22:40:55 +01:00
|
|
|
if (useFetchApi) {
|
|
|
|
|
return this.fetchImageViaFetchApi(url, priority);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.fetchImageViaTag(url, priority);
|
2024-03-01 01:17:23 +01:00
|
|
|
}
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-09-30 16:55:35 +02:00
|
|
|
method: GQLMethod.QUERY,
|
2023-10-04 22:34:32 +02:00
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
|
|
|
|
variables: Variables | undefined,
|
|
|
|
|
options?: QueryOptions<Variables, Data>,
|
2023-09-30 16:55:35 +02:00
|
|
|
): AbortabaleApolloQueryResponse<Data>;
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-09-01 20:21:59 +02:00
|
|
|
method: GQLMethod.USE_QUERY,
|
2023-10-04 22:34:32 +02:00
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
|
|
|
|
variables: Variables | undefined,
|
|
|
|
|
options?: QueryHookOptions<Data, Variables>,
|
2023-09-01 20:21:59 +02:00
|
|
|
): AbortableApolloUseQueryResponse<Data, Variables>;
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-09-01 20:21:59 +02:00
|
|
|
method: GQLMethod.USE_MUTATION,
|
2023-10-04 22:34:32 +02:00
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
2023-09-01 20:21:59 +02:00
|
|
|
variables: Variables | undefined,
|
2023-10-04 22:34:32 +02:00
|
|
|
options?: MutationHookOptions<Data, Variables>,
|
2023-09-01 20:21:59 +02:00
|
|
|
): AbortableApolloUseMutationResponse<Data, Variables>;
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-09-01 20:21:59 +02:00
|
|
|
method: GQLMethod.MUTATION,
|
2023-10-04 22:34:32 +02:00
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
|
|
|
|
variables: Variables | undefined,
|
|
|
|
|
options?: MutationOptions<Data, Variables>,
|
2023-09-01 20:21:59 +02:00
|
|
|
): AbortableApolloMutationResponse<Data>;
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-10-04 22:34:32 +02:00
|
|
|
method: GQLMethod.USE_SUBSCRIPTION,
|
|
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
|
|
|
|
variables: Variables | undefined,
|
|
|
|
|
options?: SubscriptionHookOptions<Data, Variables>,
|
|
|
|
|
): SubscriptionResult<Data, Variables>;
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
private doRequest<Data, Variables extends OperationVariables = OperationVariables>(
|
2023-09-01 20:21:59 +02:00
|
|
|
method: GQLMethod,
|
2023-10-04 22:34:32 +02:00
|
|
|
operation: DocumentNode | TypedDocumentNode<Data, Variables>,
|
|
|
|
|
variables: Variables | undefined,
|
2023-09-01 20:21:59 +02:00
|
|
|
options?:
|
2023-09-30 16:55:35 +02:00
|
|
|
| QueryOptions<Variables, Data>
|
2023-09-01 20:21:59 +02:00
|
|
|
| QueryHookOptions<Data, Variables>
|
|
|
|
|
| MutationHookOptions<Data, Variables>
|
2023-10-04 22:34:32 +02:00
|
|
|
| MutationOptions<Data, Variables>
|
|
|
|
|
| SubscriptionHookOptions<Data, Variables>,
|
2023-09-01 20:21:59 +02:00
|
|
|
):
|
2023-09-30 16:55:35 +02:00
|
|
|
| AbortabaleApolloQueryResponse<Data>
|
2023-09-01 20:21:59 +02:00
|
|
|
| AbortableApolloUseQueryResponse<Data, Variables>
|
|
|
|
|
| AbortableApolloUseMutationResponse<Data, Variables>
|
2023-10-04 22:34:32 +02:00
|
|
|
| AbortableApolloMutationResponse<Data>
|
|
|
|
|
| SubscriptionResult<Data, Variables> {
|
2023-09-12 02:36:11 +02:00
|
|
|
const { signal, abortRequest } = this.createAbortController();
|
2023-09-01 20:21:59 +02:00
|
|
|
switch (method) {
|
2023-09-30 16:55:35 +02:00
|
|
|
case GQLMethod.QUERY:
|
|
|
|
|
return {
|
|
|
|
|
response: this.graphQLClient.client.query<Data, Variables>({
|
|
|
|
|
query: operation,
|
|
|
|
|
variables,
|
|
|
|
|
...(options as QueryOptions<Variables, Data>),
|
|
|
|
|
context: {
|
|
|
|
|
...options?.context,
|
|
|
|
|
fetchOptions: {
|
2023-11-11 23:42:58 +01:00
|
|
|
signal: options?.addAbortSignal ? signal : undefined,
|
2023-09-30 16:55:35 +02:00
|
|
|
...options?.context?.fetchOptions,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
abortRequest,
|
|
|
|
|
};
|
2023-09-01 20:21:59 +02:00
|
|
|
case GQLMethod.USE_QUERY:
|
|
|
|
|
return {
|
|
|
|
|
...useQuery<Data, Variables>(operation, {
|
|
|
|
|
variables,
|
|
|
|
|
client: this.graphQLClient.client,
|
|
|
|
|
...options,
|
|
|
|
|
context: {
|
|
|
|
|
...options?.context,
|
|
|
|
|
fetchOptions: {
|
2023-11-11 23:42:58 +01:00
|
|
|
signal: options?.addAbortSignal ? signal : undefined,
|
2023-09-01 20:21:59 +02:00
|
|
|
...options?.context?.fetchOptions,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
abortRequest,
|
|
|
|
|
};
|
|
|
|
|
case GQLMethod.USE_MUTATION:
|
|
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const mutationResult = useMutation<Data, Variables>(operation, {
|
|
|
|
|
variables,
|
|
|
|
|
client: this.graphQLClient.client,
|
|
|
|
|
...(options as MutationHookOptions<Data, Variables>),
|
|
|
|
|
context: {
|
|
|
|
|
...options?.context,
|
|
|
|
|
fetchOptions: {
|
2023-11-11 23:42:58 +01:00
|
|
|
signal: options?.addAbortSignal ? signal : undefined,
|
2023-09-01 20:21:59 +02:00
|
|
|
...options?.context?.fetchOptions,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return [mutationResult[0], { ...mutationResult[1], abortRequest }];
|
|
|
|
|
case GQLMethod.MUTATION:
|
|
|
|
|
return {
|
|
|
|
|
response: this.graphQLClient.client.mutate<Data, Variables>({
|
|
|
|
|
mutation: operation,
|
|
|
|
|
variables,
|
|
|
|
|
...(options as MutationOptions<Data, Variables>),
|
|
|
|
|
context: {
|
|
|
|
|
...options?.context,
|
|
|
|
|
fetchOptions: {
|
2023-11-11 23:42:58 +01:00
|
|
|
signal: options?.addAbortSignal ? signal : undefined,
|
2023-09-01 20:21:59 +02:00
|
|
|
...options?.context?.fetchOptions,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
abortRequest,
|
|
|
|
|
};
|
2023-10-04 22:34:32 +02:00
|
|
|
case GQLMethod.USE_SUBSCRIPTION:
|
|
|
|
|
return useSubscription<Data, Variables>(operation, {
|
|
|
|
|
client: this.graphQLClient.client,
|
|
|
|
|
variables,
|
|
|
|
|
...(options as SubscriptionHookOptions<Data, Variables>),
|
|
|
|
|
});
|
2023-09-01 20:21:59 +02:00
|
|
|
default:
|
|
|
|
|
throw new Error(`unexpected GQLRequest type "${method}"`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-25 21:37:45 +01:00
|
|
|
public getGlobalMeta(
|
|
|
|
|
options?: QueryOptions<GetGlobalMetadatasQueryVariables, GetGlobalMetadatasQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetGlobalMetadatasQuery> {
|
|
|
|
|
return this.doRequest(GQLMethod.QUERY, GET_GLOBAL_METADATAS, {}, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:24:40 +02:00
|
|
|
public useGetGlobalMeta(
|
|
|
|
|
options?: QueryHookOptions<GetGlobalMetadatasQuery, GetGlobalMetadatasQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetGlobalMetadatasQuery, GetGlobalMetadatasQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_GLOBAL_METADATAS, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public setGlobalMetadata(
|
|
|
|
|
key: string,
|
|
|
|
|
value: any,
|
|
|
|
|
options?: MutationOptions<SetGlobalMetadataMutation, SetGlobalMetadataMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<SetGlobalMetadataMutation> {
|
2024-04-27 22:28:55 +02:00
|
|
|
return this.doRequest<SetGlobalMetadataMutation, SetGlobalMetadataMutationVariables>(
|
2023-09-01 20:24:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
SET_GLOBAL_METADATA,
|
|
|
|
|
{ input: { meta: { key, value: `${value}` } } },
|
2024-04-27 22:28:55 +02:00
|
|
|
{
|
|
|
|
|
update(cache, { data }) {
|
|
|
|
|
cache.modify({
|
|
|
|
|
fields: {
|
|
|
|
|
metas(existingMetas, { readField }) {
|
|
|
|
|
if (!existingMetas) {
|
|
|
|
|
return existingMetas;
|
|
|
|
|
}
|
2023-10-16 00:05:51 +02:00
|
|
|
|
2024-04-27 22:28:55 +02:00
|
|
|
const exists = existingMetas.nodes.some(
|
|
|
|
|
// eslint-disable-next-line no-underscore-dangle
|
|
|
|
|
(meta: Reference) => readField('key', meta) === key,
|
|
|
|
|
);
|
|
|
|
|
if (exists) {
|
|
|
|
|
return existingMetas;
|
|
|
|
|
}
|
2023-10-16 00:05:51 +02:00
|
|
|
|
2024-04-27 22:28:55 +02:00
|
|
|
const newMetaRef = cache.writeFragment({
|
|
|
|
|
data: data!.setGlobalMeta.meta,
|
|
|
|
|
fragment: GLOBAL_METADATA,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return [...existingMetas, newMetaRef];
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
...options,
|
|
|
|
|
},
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:25:46 +02:00
|
|
|
public useGetAbout(
|
|
|
|
|
options?: QueryHookOptions<GetAboutQuery, GetAboutQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetAboutQuery, GetAboutQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_ABOUT, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-09 23:08:27 +01:00
|
|
|
public useCheckForServerUpdate(
|
2023-09-01 20:26:06 +02:00
|
|
|
options?: QueryHookOptions<CheckForServerUpdatesQuery, CheckForServerUpdatesQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<CheckForServerUpdatesQuery, CheckForServerUpdatesQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, CHECK_FOR_SERVER_UPDATES, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-09 23:08:27 +01:00
|
|
|
public useCheckForWebUIUpdate(
|
|
|
|
|
options?: QueryHookOptions<CheckForWebuiUpdateQuery, CheckForWebuiUpdateQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<CheckForWebuiUpdateQuery, CheckForWebuiUpdateQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, CHECK_FOR_WEBUI_UPDATE, {}, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public updateWebUI(
|
|
|
|
|
options?: MutationOptions<UpdateWebuiMutation, UpdateWebuiMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateWebuiMutation> {
|
|
|
|
|
return this.doRequest(GQLMethod.MUTATION, UPDATE_WEBUI, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:28:23 +02:00
|
|
|
public useGetExtensionList(
|
|
|
|
|
options?: QueryHookOptions<GetExtensionsQuery, GetExtensionsQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetExtensionsQuery, GetExtensionsQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_EXTENSIONS, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:28:23 +02:00
|
|
|
public useExtensionListFetch(
|
|
|
|
|
options?: MutationHookOptions<GetExtensionsFetchMutation, GetExtensionsFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<GetExtensionsFetchMutation, GetExtensionsFetchMutationVariables> {
|
2023-11-04 22:40:38 +01:00
|
|
|
const [mutate, result] = this.doRequest(
|
2023-10-16 00:05:51 +02:00
|
|
|
GQLMethod.USE_MUTATION,
|
|
|
|
|
GET_EXTENSIONS_FETCH,
|
|
|
|
|
{},
|
|
|
|
|
{ refetchQueries: [GET_EXTENSIONS], ...options },
|
|
|
|
|
);
|
2023-11-18 19:55:35 +01:00
|
|
|
const [, setUpdatedCache] = useState({});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (result.loading) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!result.data?.fetchExtensions.extensions) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-04 22:40:38 +01:00
|
|
|
|
2023-11-05 22:37:28 +01:00
|
|
|
this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, result);
|
2023-11-18 19:55:35 +01:00
|
|
|
setUpdatedCache({});
|
|
|
|
|
}, [result.loading]);
|
|
|
|
|
|
2023-11-05 22:37:28 +01:00
|
|
|
const cachedResult = this.cache.getResponseFor<typeof result>(EXTENSION_LIST_CACHE_KEY, undefined, 1000 * 60);
|
2023-11-18 19:55:35 +01:00
|
|
|
const normalizedCachedResult = useMemo(
|
|
|
|
|
() =>
|
|
|
|
|
!cachedResult
|
|
|
|
|
? result
|
|
|
|
|
: {
|
|
|
|
|
...cachedResult,
|
|
|
|
|
data: !cachedResult?.data?.fetchExtensions.extensions
|
|
|
|
|
? cachedResult?.data
|
|
|
|
|
: {
|
|
|
|
|
...cachedResult.data,
|
|
|
|
|
fetchExtensions: {
|
|
|
|
|
...cachedResult.data.fetchExtensions,
|
|
|
|
|
extensions: cachedResult.data.fetchExtensions.extensions.map(
|
|
|
|
|
(extension) =>
|
|
|
|
|
this.graphQLClient.client.cache.readFragment<
|
|
|
|
|
GetExtensionsFetchMutation['fetchExtensions']['extensions'][0]
|
|
|
|
|
>({
|
|
|
|
|
id: this.graphQLClient.client.cache.identify(extension),
|
|
|
|
|
fragment: FULL_EXTENSION_FIELDS,
|
|
|
|
|
}) ?? extension,
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-04-27 22:28:55 +02:00
|
|
|
[this.cache.getFetchTimestampFor(EXTENSION_LIST_CACHE_KEY, undefined), result.loading],
|
2023-11-18 19:55:35 +01:00
|
|
|
);
|
2023-11-04 22:40:38 +01:00
|
|
|
|
2023-11-05 22:37:28 +01:00
|
|
|
const wrappedMutate = async (mutateOptions: Parameters<typeof mutate>[0]) => {
|
2023-11-04 22:40:38 +01:00
|
|
|
if (cachedResult) {
|
2023-11-05 22:37:28 +01:00
|
|
|
return normalizedCachedResult;
|
2023-11-04 22:40:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mutate(mutateOptions);
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-05 22:37:28 +01:00
|
|
|
return [wrappedMutate, normalizedCachedResult];
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:28:23 +02:00
|
|
|
public installExternalExtension(
|
|
|
|
|
extensionFile: File,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<InstallExternalExtensionMutation, InstallExternalExtensionMutationVariables>,
|
2023-09-01 20:28:23 +02:00
|
|
|
): AbortableApolloMutationResponse<InstallExternalExtensionMutation> {
|
2024-01-29 20:59:27 +01:00
|
|
|
const result = this.doRequest<InstallExternalExtensionMutation, InstallExternalExtensionMutationVariables>(
|
2023-09-01 20:28:23 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
INSTALL_EXTERNAL_EXTENSION,
|
|
|
|
|
{ file: extensionFile },
|
2023-10-16 00:05:51 +02:00
|
|
|
{ refetchQueries: [GET_EXTENSIONS], ...options },
|
2023-09-01 20:28:23 +02:00
|
|
|
);
|
2024-01-29 20:59:27 +01:00
|
|
|
|
|
|
|
|
result.response.then((response) => {
|
|
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'sources' });
|
|
|
|
|
const cachedExtensions = this.cache.getResponseFor<MutationResult<GetExtensionsFetchMutation>>(
|
|
|
|
|
EXTENSION_LIST_CACHE_KEY,
|
|
|
|
|
undefined,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const installedExtension = response.data?.installExternalExtension.extension;
|
|
|
|
|
|
|
|
|
|
if (!cachedExtensions || !cachedExtensions.data) {
|
|
|
|
|
this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, {
|
|
|
|
|
data: {
|
|
|
|
|
fetchExtensions: {
|
|
|
|
|
extensions: [installedExtension],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isExtensionCached = !!cachedExtensions.data.fetchExtensions.extensions.find(
|
|
|
|
|
(extension) => installedExtension?.pkgName === extension.pkgName,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const updatedCachedExtensions: MutationResult<GetExtensionsFetchMutation> = {
|
|
|
|
|
...cachedExtensions,
|
|
|
|
|
data: {
|
|
|
|
|
...cachedExtensions.data,
|
|
|
|
|
fetchExtensions: {
|
|
|
|
|
...cachedExtensions.data.fetchExtensions,
|
|
|
|
|
extensions: isExtensionCached
|
|
|
|
|
? cachedExtensions.data.fetchExtensions.extensions.map((extension) => {
|
|
|
|
|
const isUpdatedExtension = installedExtension?.pkgName === extension.pkgName;
|
|
|
|
|
if (!isUpdatedExtension) {
|
|
|
|
|
return extension;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...extension,
|
|
|
|
|
...installedExtension,
|
|
|
|
|
hasUpdate: installedExtension?.versionCode < extension.versionCode,
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
: [
|
|
|
|
|
...cachedExtensions.data.fetchExtensions.extensions,
|
|
|
|
|
installedExtension as (typeof cachedExtensions.data.fetchExtensions.extensions)[number],
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, updatedCachedExtensions);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:28:23 +02:00
|
|
|
public updateExtension(
|
|
|
|
|
id: string,
|
2024-01-29 20:56:09 +01:00
|
|
|
{ isObsolete = false, ...patch }: UpdateExtensionPatchInput & { isObsolete?: boolean },
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<UpdateExtensionMutation, UpdateExtensionMutationVariables>,
|
2023-09-01 20:28:23 +02:00
|
|
|
): AbortableApolloMutationResponse<UpdateExtensionMutation> {
|
2023-10-16 00:05:51 +02:00
|
|
|
const result = this.doRequest<UpdateExtensionMutation, UpdateExtensionMutationVariables>(
|
2023-09-01 20:28:23 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_EXTENSION,
|
|
|
|
|
{ input: { id, patch } },
|
2023-11-05 22:37:28 +01:00
|
|
|
options,
|
2023-09-01 20:28:23 +02:00
|
|
|
);
|
2023-10-16 00:05:51 +02:00
|
|
|
|
2023-11-24 03:20:16 +01:00
|
|
|
result.response.then((response) => {
|
2023-10-16 00:05:51 +02:00
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'sources' });
|
2023-11-24 03:20:16 +01:00
|
|
|
const cachedExtensions = this.cache.getResponseFor<MutationResult<GetExtensionsFetchMutation>>(
|
|
|
|
|
EXTENSION_LIST_CACHE_KEY,
|
|
|
|
|
undefined,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!cachedExtensions || !cachedExtensions.data) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const updatedCachedExtensions: MutationResult<GetExtensionsFetchMutation> = {
|
|
|
|
|
...cachedExtensions,
|
|
|
|
|
data: {
|
|
|
|
|
...cachedExtensions.data,
|
|
|
|
|
fetchExtensions: {
|
|
|
|
|
...cachedExtensions.data.fetchExtensions,
|
2024-01-29 20:56:09 +01:00
|
|
|
extensions: cachedExtensions.data.fetchExtensions.extensions
|
|
|
|
|
.filter((extension) => {
|
2024-02-01 22:58:01 +01:00
|
|
|
if (!isObsolete) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-29 20:56:09 +01:00
|
|
|
const isUpdatedExtension = id === extension.pkgName;
|
2024-02-01 22:58:01 +01:00
|
|
|
return !isUpdatedExtension;
|
2024-01-29 20:56:09 +01:00
|
|
|
})
|
|
|
|
|
.map((extension) => {
|
|
|
|
|
const isUpdatedExtension = id === extension.pkgName;
|
|
|
|
|
if (!isUpdatedExtension) {
|
|
|
|
|
return extension;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...extension,
|
|
|
|
|
...response.data?.updateExtension.extension,
|
|
|
|
|
};
|
|
|
|
|
}),
|
2023-11-24 03:20:16 +01:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, updatedCachedExtensions);
|
2023-10-16 00:05:51 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getExtensionIconUrl(extension: string): string {
|
|
|
|
|
return this.getValidImgUrlFor(`extension/icon/${extension}`);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:29:19 +02:00
|
|
|
public useGetSourceList(
|
|
|
|
|
options?: QueryHookOptions<GetSourcesQuery, GetSourcesQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetSourcesQuery, GetSourcesQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_SOURCES, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:29:19 +02:00
|
|
|
public useGetSource(
|
|
|
|
|
id: string,
|
|
|
|
|
options?: QueryHookOptions<GetSourceQuery, GetSourceQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetSourceQuery, GetSourceQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_SOURCE, { id }, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-08 00:06:24 +02:00
|
|
|
public useGetSourceMangas(
|
|
|
|
|
input: FetchSourceMangaInput,
|
2023-09-12 02:36:11 +02:00
|
|
|
initialPages: number = 1,
|
|
|
|
|
options?: ApolloPaginatedMutationOptions<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>,
|
2023-09-08 00:06:24 +02:00
|
|
|
): AbortableApolloUseMutationPaginatedResponse<
|
|
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables
|
|
|
|
|
> {
|
2023-09-12 02:36:11 +02:00
|
|
|
type MutationResult = AbortableApolloUseMutationPaginatedResponse<
|
|
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables
|
|
|
|
|
>[1];
|
|
|
|
|
type MutationDataResult = MutationResult[number];
|
|
|
|
|
|
2023-09-08 00:06:24 +02:00
|
|
|
const createPaginatedResult = (
|
2023-09-12 02:36:11 +02:00
|
|
|
result?: Partial<AbortableApolloUseMutationPaginatedResponse[1][number]> | null,
|
|
|
|
|
page?: number,
|
|
|
|
|
) => this.createPaginatedResult(result, input.page, page);
|
|
|
|
|
|
|
|
|
|
const getVariablesFor = (page: number): GetSourceMangasFetchMutationVariables => ({
|
|
|
|
|
input: {
|
|
|
|
|
...input,
|
|
|
|
|
page,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const isRevalidationDoneRef = useRef(false);
|
|
|
|
|
const activeRevalidationRef = useRef<
|
|
|
|
|
| [
|
|
|
|
|
ForInput: GetSourceMangasFetchMutationVariables,
|
|
|
|
|
Request: Promise<unknown>,
|
|
|
|
|
AbortRequest: AbortableRequest['abortRequest'],
|
|
|
|
|
]
|
|
|
|
|
| null
|
|
|
|
|
>(null);
|
|
|
|
|
const abortRequestRef = useRef<AbortableRequest['abortRequest']>(() => {});
|
|
|
|
|
const resultRef = useRef<(MutationDataResult & { forInput: string }) | null>(null);
|
|
|
|
|
const result = resultRef.current;
|
|
|
|
|
|
|
|
|
|
const [, setTriggerRerender] = useState(0);
|
|
|
|
|
const triggerRerender = () => setTriggerRerender((prev) => prev + 1);
|
|
|
|
|
const setResult = (nextResult: typeof resultRef.current) => {
|
|
|
|
|
resultRef.current = nextResult;
|
|
|
|
|
triggerRerender();
|
2023-09-08 00:06:24 +02:00
|
|
|
};
|
|
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
const cachedPages = this.cache.getResponseFor<Set<number>>(CACHE_PAGES_KEY, getVariablesFor(0)) ?? new Set();
|
|
|
|
|
const cachedResults = [...cachedPages]
|
|
|
|
|
.map(
|
|
|
|
|
(cachedPage) =>
|
|
|
|
|
this.cache.getResponseFor<MutationDataResult>(CACHE_RESULTS_KEY, getVariablesFor(cachedPage))!,
|
|
|
|
|
)
|
|
|
|
|
.sort((a, b) => a.size - b.size);
|
|
|
|
|
const areFetchingInitialPages = !!this.cache.getResponseFor<boolean>(
|
|
|
|
|
CACHE_INITIAL_PAGES_FETCHING_KEY,
|
|
|
|
|
getVariablesFor(0),
|
2023-09-08 00:06:24 +02:00
|
|
|
);
|
|
|
|
|
|
2023-10-29 20:51:53 +01:00
|
|
|
const areInitialPagesFetched =
|
|
|
|
|
cachedResults.length >= initialPages ||
|
|
|
|
|
(!!cachedResults.length && !cachedResults[cachedResults.length - 1].data?.fetchSourceManga.hasNextPage);
|
2023-09-12 02:36:11 +02:00
|
|
|
const isResultForCurrentInput = result?.forInput === JSON.stringify(getVariablesFor(0));
|
|
|
|
|
const lastPage = cachedPages.size ? Math.max(...cachedPages) : input.page;
|
|
|
|
|
const nextPage = isResultForCurrentInput ? result.size : lastPage;
|
|
|
|
|
|
|
|
|
|
const paginatedResult =
|
|
|
|
|
isResultForCurrentInput && areInitialPagesFetched ? result : createPaginatedResult(undefined, nextPage);
|
|
|
|
|
paginatedResult.abortRequest = abortRequestRef.current;
|
|
|
|
|
|
|
|
|
|
// make sure that the result is always for the current input
|
|
|
|
|
resultRef.current = { forInput: JSON.stringify(getVariablesFor(0)), ...paginatedResult };
|
|
|
|
|
|
|
|
|
|
const hasCachedResult = !!this.cache.getResponseFor(CACHE_RESULTS_KEY, getVariablesFor(nextPage));
|
|
|
|
|
|
|
|
|
|
const revalidatePage = async (pageToRevalidate: number, maxPage: number, signal: AbortSignal) =>
|
|
|
|
|
this.revalidatePage(
|
2023-11-11 23:43:22 +01:00
|
|
|
input.source,
|
2023-09-12 02:36:11 +02:00
|
|
|
CACHE_RESULTS_KEY,
|
|
|
|
|
CACHE_PAGES_KEY,
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
options,
|
|
|
|
|
(cachedResult, revalidatedResult) =>
|
|
|
|
|
!cachedResult ||
|
|
|
|
|
!cachedResult.data?.fetchSourceManga.mangas.length ||
|
|
|
|
|
cachedResult.data.fetchSourceManga.mangas.some(
|
|
|
|
|
(manga, index) => manga.id !== revalidatedResult.data?.fetchSourceManga.mangas[index]?.id,
|
|
|
|
|
),
|
|
|
|
|
(revalidatedResult) => !!revalidatedResult.data?.fetchSourceManga.hasNextPage,
|
|
|
|
|
pageToRevalidate,
|
|
|
|
|
maxPage,
|
|
|
|
|
signal,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const revalidate = async (
|
|
|
|
|
maxPage: number,
|
|
|
|
|
abortRequest: AbortableRequest['abortRequest'],
|
|
|
|
|
signal: AbortSignal,
|
|
|
|
|
) =>
|
|
|
|
|
this.revalidatePages(
|
|
|
|
|
activeRevalidationRef.current,
|
|
|
|
|
(isDone) => {
|
|
|
|
|
isRevalidationDoneRef.current = isDone;
|
|
|
|
|
},
|
|
|
|
|
(activeRevalidation) => {
|
|
|
|
|
activeRevalidationRef.current = activeRevalidation;
|
|
|
|
|
},
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
(isValidating) => {
|
|
|
|
|
setResult({
|
|
|
|
|
...createPaginatedResult(resultRef.current),
|
|
|
|
|
isValidating,
|
|
|
|
|
forInput: JSON.stringify(getVariablesFor(0)),
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
revalidatePage,
|
|
|
|
|
maxPage,
|
|
|
|
|
abortRequest,
|
|
|
|
|
signal,
|
|
|
|
|
);
|
2023-09-08 00:06:24 +02:00
|
|
|
|
|
|
|
|
// wrap "mutate" function to align with the expected type, which allows only passing a "page" argument
|
2023-09-12 02:36:11 +02:00
|
|
|
const wrappedMutate = async (newPage: number) =>
|
|
|
|
|
this.fetchPaginatedMutationPage<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>(
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
(abortRequest) => {
|
|
|
|
|
abortRequestRef.current = abortRequest;
|
2023-09-08 00:06:24 +02:00
|
|
|
},
|
2023-09-12 02:36:11 +02:00
|
|
|
() => ({ forType: input.type, forQuery: input.query }),
|
|
|
|
|
createPaginatedResult,
|
|
|
|
|
setResult,
|
|
|
|
|
revalidate,
|
|
|
|
|
options,
|
|
|
|
|
GET_SOURCE_MANGAS_FETCH,
|
|
|
|
|
CACHE_PAGES_KEY,
|
|
|
|
|
CACHE_RESULTS_KEY,
|
|
|
|
|
cachedPages,
|
|
|
|
|
newPage,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.fetchInitialPages(
|
|
|
|
|
options,
|
|
|
|
|
areFetchingInitialPages,
|
|
|
|
|
areInitialPagesFetched,
|
|
|
|
|
(isDone) => {
|
|
|
|
|
isRevalidationDoneRef.current = isDone;
|
|
|
|
|
},
|
|
|
|
|
CACHE_INITIAL_PAGES_FETCHING_KEY,
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
initialPages,
|
|
|
|
|
wrappedMutate,
|
|
|
|
|
(fetchedResult) => !!fetchedResult.data?.fetchSourceManga.hasNextPage,
|
|
|
|
|
);
|
2023-09-08 00:06:24 +02:00
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
this.revalidateInitialPages(
|
|
|
|
|
isRevalidationDoneRef.current,
|
|
|
|
|
cachedResults.length,
|
|
|
|
|
cachedPages,
|
|
|
|
|
(isDone) => {
|
|
|
|
|
isRevalidationDoneRef.current = isDone;
|
|
|
|
|
},
|
|
|
|
|
getVariablesFor,
|
|
|
|
|
triggerRerender,
|
|
|
|
|
revalidate,
|
|
|
|
|
);
|
2023-09-08 00:06:24 +02:00
|
|
|
|
2023-11-05 22:40:35 +01:00
|
|
|
const normalizedCachedResults = cachedResults.map((cachedResult) => {
|
|
|
|
|
const hasResults = cachedResult.data?.fetchSourceManga.mangas;
|
|
|
|
|
if (!hasResults) {
|
|
|
|
|
return cachedResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...cachedResult,
|
|
|
|
|
data: {
|
|
|
|
|
...cachedResult.data,
|
|
|
|
|
fetchSourceManga: {
|
|
|
|
|
...cachedResult.data?.fetchSourceManga,
|
|
|
|
|
mangas: cachedResult.data?.fetchSourceManga.mangas.map(
|
|
|
|
|
(manga) =>
|
|
|
|
|
this.graphQLClient.client.cache.readFragment<typeof manga>({
|
|
|
|
|
id: this.graphQLClient.client.cache.identify(manga),
|
|
|
|
|
fragment: BASE_MANGA_FIELDS,
|
|
|
|
|
fragmentName: 'BASE_MANGA_FIELDS',
|
|
|
|
|
}) ?? manga,
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-12 02:36:11 +02:00
|
|
|
return this.returnPaginatedMutationResult(
|
|
|
|
|
areInitialPagesFetched,
|
2023-11-05 22:40:35 +01:00
|
|
|
normalizedCachedResults,
|
2023-09-12 02:36:11 +02:00
|
|
|
getVariablesFor,
|
|
|
|
|
paginatedResult,
|
|
|
|
|
wrappedMutate,
|
|
|
|
|
hasCachedResult,
|
|
|
|
|
createPaginatedResult,
|
|
|
|
|
);
|
2023-09-08 00:06:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public useGetSourcePopularMangas(
|
|
|
|
|
sourceId: string,
|
|
|
|
|
initialPages?: number,
|
2023-09-12 02:36:11 +02:00
|
|
|
options?: ApolloPaginatedMutationOptions<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationPaginatedResponse<
|
|
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables
|
|
|
|
|
> {
|
|
|
|
|
return this.useGetSourceMangas(
|
|
|
|
|
{ type: FetchSourceMangaType.Popular, source: sourceId, page: 1 },
|
|
|
|
|
initialPages,
|
|
|
|
|
options,
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useGetSourceLatestMangas(
|
|
|
|
|
sourceId: string,
|
|
|
|
|
initialPages?: number,
|
2023-09-12 02:36:11 +02:00
|
|
|
options?: ApolloPaginatedMutationOptions<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationPaginatedResponse<
|
|
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables
|
|
|
|
|
> {
|
|
|
|
|
return this.useGetSourceMangas(
|
|
|
|
|
{ type: FetchSourceMangaType.Latest, source: sourceId, page: 1 },
|
|
|
|
|
initialPages,
|
|
|
|
|
options,
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-25 23:32:26 +02:00
|
|
|
public setSourcePreferences(
|
|
|
|
|
source: string,
|
|
|
|
|
change: SourcePreferenceChangeInput,
|
|
|
|
|
options?: MutationOptions<UpdateSourcePreferencesMutation, UpdateSourcePreferencesMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateSourcePreferencesMutation> {
|
2023-10-16 00:05:51 +02:00
|
|
|
return this.doRequest(GQLMethod.MUTATION, UPDATE_SOURCE_PREFERENCES, { input: { source, change } }, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useSourceSearch(
|
2023-09-08 00:06:24 +02:00
|
|
|
source: string,
|
2023-09-12 02:36:11 +02:00
|
|
|
query?: string,
|
2023-09-08 00:06:24 +02:00
|
|
|
filters?: FilterChangeInput[],
|
2023-09-12 02:36:11 +02:00
|
|
|
initialPages?: number,
|
|
|
|
|
options?: ApolloPaginatedMutationOptions<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>,
|
2023-09-08 00:06:24 +02:00
|
|
|
): AbortableApolloUseMutationPaginatedResponse<
|
|
|
|
|
GetSourceMangasFetchMutation,
|
|
|
|
|
GetSourceMangasFetchMutationVariables
|
|
|
|
|
> {
|
2023-09-12 02:36:11 +02:00
|
|
|
return this.useGetSourceMangas(
|
|
|
|
|
{ type: FetchSourceMangaType.Search, source, query, filters, page: 1 },
|
|
|
|
|
initialPages,
|
|
|
|
|
options,
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useGetManga(
|
|
|
|
|
mangaId: number | string,
|
2023-09-08 00:44:01 +02:00
|
|
|
options?: QueryHookOptions<GetMangaQuery, GetMangaQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetMangaQuery, GetMangaQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_MANGA, { id: Number(mangaId) }, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-26 20:50:51 +01:00
|
|
|
public getManga(
|
|
|
|
|
mangaId: number | string,
|
|
|
|
|
options?: QueryOptions<GetMangaQueryVariables, GetMangaQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetMangaQuery> {
|
|
|
|
|
return this.doRequest(GQLMethod.QUERY, GET_MANGA, { id: Number(mangaId) }, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getMangaToMigrate(
|
|
|
|
|
mangaId: number | string,
|
|
|
|
|
{
|
|
|
|
|
migrateChapters = false,
|
|
|
|
|
migrateCategories = false,
|
2024-04-20 23:51:47 +02:00
|
|
|
migrateTracking = false,
|
2024-03-16 13:45:54 +01:00
|
|
|
deleteChapters = false,
|
2024-01-26 20:50:51 +01:00
|
|
|
apolloOptions: options,
|
2024-04-20 23:51:47 +02:00
|
|
|
}: Partial<MetadataMigrationSettings> & {
|
2024-01-26 20:50:51 +01:00
|
|
|
apolloOptions?: QueryOptions<GetMangaToMigrateQueryVariables, GetMangaToMigrateQuery>;
|
|
|
|
|
} = {},
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetMangaToMigrateQuery> {
|
|
|
|
|
return this.doRequest(
|
|
|
|
|
GQLMethod.QUERY,
|
|
|
|
|
GET_MANGA_TO_MIGRATE,
|
2024-04-20 23:51:47 +02:00
|
|
|
{
|
|
|
|
|
id: Number(mangaId),
|
|
|
|
|
getChapterData: migrateChapters || deleteChapters,
|
|
|
|
|
migrateCategories,
|
|
|
|
|
migrateTracking,
|
|
|
|
|
},
|
2024-01-26 20:50:51 +01:00
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-08 00:44:01 +02:00
|
|
|
public getMangaFetch(
|
2023-05-18 13:25:19 +02:00
|
|
|
mangaId: number | string,
|
2023-09-08 00:44:01 +02:00
|
|
|
options?: MutationOptions<GetMangaFetchMutation, GetMangaFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<GetMangaFetchMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<GetMangaFetchMutation, GetMangaFetchMutationVariables>(
|
2023-09-08 00:44:01 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
GET_MANGA_FETCH,
|
|
|
|
|
{
|
|
|
|
|
input: {
|
|
|
|
|
id: Number(mangaId),
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-08 00:44:01 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-26 20:50:51 +01:00
|
|
|
public getMangaToMigrateToFetch(
|
|
|
|
|
mangaId: number | string,
|
|
|
|
|
{
|
|
|
|
|
migrateChapters = false,
|
|
|
|
|
migrateCategories = false,
|
2024-04-20 23:51:47 +02:00
|
|
|
migrateTracking = false,
|
2024-01-26 20:50:51 +01:00
|
|
|
apolloOptions: options,
|
2024-04-20 23:51:47 +02:00
|
|
|
}: Partial<Omit<MetadataMigrationSettings, 'deleteChapters'>> & {
|
2024-01-26 20:50:51 +01:00
|
|
|
apolloOptions?: MutationOptions<
|
|
|
|
|
GetMangaToMigrateToFetchMutation,
|
|
|
|
|
GetMangaToMigrateToFetchMutationVariables
|
|
|
|
|
>;
|
|
|
|
|
} = {},
|
|
|
|
|
): AbortableApolloMutationResponse<GetMangaToMigrateToFetchMutation> {
|
|
|
|
|
return this.doRequest<GetMangaToMigrateToFetchMutation, GetMangaToMigrateToFetchMutationVariables>(
|
|
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
GET_MANGA_TO_MIGRATE_TO_FETCH,
|
|
|
|
|
{
|
|
|
|
|
id: Number(mangaId),
|
|
|
|
|
migrateChapters,
|
|
|
|
|
migrateCategories,
|
2024-04-20 23:51:47 +02:00
|
|
|
migrateTracking,
|
2024-01-26 20:50:51 +01:00
|
|
|
},
|
|
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-19 21:01:21 +02:00
|
|
|
public useGetMangas(
|
|
|
|
|
variables: GetMangasQueryVariables,
|
|
|
|
|
options?: QueryHookOptions<GetMangasQuery, GetMangasQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetMangasQuery, GetMangasQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_MANGAS, variables, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:17:41 +01:00
|
|
|
public getMangas(
|
|
|
|
|
variables: GetMangasQueryVariables,
|
|
|
|
|
options?: QueryOptions<GetMangasQueryVariables, GetMangasQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetMangasQuery> {
|
|
|
|
|
return this.doRequest(GQLMethod.QUERY, GET_MANGAS, variables, options);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-26 20:50:51 +01:00
|
|
|
public useGetMigratableSourceMangas(
|
|
|
|
|
sourceId: string,
|
|
|
|
|
options?: QueryHookOptions<GetMigratableSourceMangasQuery, GetMigratableSourceMangasQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetMigratableSourceMangasQuery, GetMigratableSourceMangasQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_MIGRATABLE_SOURCE_MANGAS, { sourceId }, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:33:35 +02:00
|
|
|
public useUpdateMangaCategories(
|
|
|
|
|
options?: MutationHookOptions<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables> {
|
2023-10-16 00:05:51 +02:00
|
|
|
const [mutate, result] = this.doRequest(GQLMethod.USE_MUTATION, UPDATE_MANGA_CATEGORIES, undefined, options);
|
|
|
|
|
|
|
|
|
|
const wrappedMutate = (mutateOptions: Parameters<typeof mutate>[0]) =>
|
|
|
|
|
mutate({
|
|
|
|
|
onCompleted: () => {
|
2023-12-25 21:37:45 +01:00
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'categories' });
|
|
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'mangas' });
|
2023-10-16 00:05:51 +02:00
|
|
|
},
|
|
|
|
|
...mutateOptions,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return [wrappedMutate, result];
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-25 21:37:45 +01:00
|
|
|
public updateMangasCategories(
|
|
|
|
|
mangaIds: number[],
|
|
|
|
|
patch: UpdateMangaCategoriesPatchInput,
|
|
|
|
|
options?: MutationOptions<UpdateMangasCategoriesMutation, UpdateMangasCategoriesMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateMangasCategoriesMutation> {
|
|
|
|
|
const response = this.doRequest(
|
|
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_MANGAS_CATEGORIES,
|
|
|
|
|
{ input: { ids: mangaIds, patch } },
|
|
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
response.response.then(() => {
|
|
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'categories' });
|
|
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'mangas' });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:33:35 +02:00
|
|
|
public updateManga(
|
|
|
|
|
id: number,
|
2024-03-02 15:26:15 +01:00
|
|
|
patch: { updateManga: UpdateMangaPatchInput; updateMangaCategories?: UpdateMangaCategoriesPatchInput },
|
2023-10-16 00:05:51 +02:00
|
|
|
options?: MutationOptions<UpdateMangaMutation, UpdateMangaMutationVariables>,
|
2023-09-01 20:33:35 +02:00
|
|
|
): AbortableApolloMutationResponse<UpdateMangaMutation> {
|
2023-10-16 00:05:51 +02:00
|
|
|
const result = this.doRequest<UpdateMangaMutation, UpdateMangaMutationVariables>(
|
2023-09-01 20:33:35 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_MANGA,
|
2024-03-02 15:26:15 +01:00
|
|
|
{
|
|
|
|
|
input: { id, patch: patch.updateManga },
|
|
|
|
|
updateCategoryInput: { id, patch: patch.updateMangaCategories ?? {} },
|
|
|
|
|
updateCategories: !!patch.updateMangaCategories,
|
|
|
|
|
},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:33:35 +02:00
|
|
|
);
|
2023-10-16 00:05:51 +02:00
|
|
|
|
|
|
|
|
result.response.then(() => {
|
2024-01-17 13:45:30 +01:00
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'categories' });
|
|
|
|
|
this.graphQLClient.client.cache.evict({ broadcast: true, fieldName: 'mangas' });
|
2023-10-16 00:05:51 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-25 21:37:45 +01:00
|
|
|
public updateMangas(
|
|
|
|
|
ids: number[],
|
2024-03-02 15:28:58 +01:00
|
|
|
patch: { updateMangas: UpdateMangaPatchInput; updateMangasCategories?: UpdateMangaCategoriesPatchInput },
|
2023-12-25 21:37:45 +01:00
|
|
|
options?: MutationOptions<UpdateMangasMutation, UpdateMangasMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateMangasMutation> {
|
|
|
|
|
const result = this.doRequest<UpdateMangasMutation, UpdateMangasMutationVariables>(
|
|
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_MANGAS,
|
2024-03-02 15:28:58 +01:00
|
|
|
{
|
|
|
|
|
input: { ids, patch: patch.updateMangas },
|
|
|
|
|
updateCategoryInput: { ids, patch: patch.updateMangasCategories ?? {} },
|
|
|
|
|
updateCategories: !!patch.updateMangasCategories,
|
|
|
|
|
},
|
2023-12-25 21:37:45 +01:00
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
result.response.then(() => {
|
|
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'categories' });
|
|
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'category' });
|
|
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'mangas' });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:33:35 +02:00
|
|
|
public setMangaMeta(
|
|
|
|
|
mangaId: number,
|
|
|
|
|
key: string,
|
|
|
|
|
value: any,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<SetMangaMetadataMutation, SetMangaMetadataMutationVariables>,
|
2023-09-01 20:33:35 +02:00
|
|
|
): AbortableApolloMutationResponse<SetMangaMetadataMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(
|
2023-09-01 20:33:35 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
SET_MANGA_METADATA,
|
|
|
|
|
{
|
|
|
|
|
input: { meta: { mangaId, key, value: `${value}` } },
|
|
|
|
|
},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:33:35 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-30 16:55:35 +02:00
|
|
|
public useGetChapters(
|
|
|
|
|
variables: GetChaptersQueryVariables,
|
|
|
|
|
options?: QueryHookOptions<GetChaptersQuery, GetChaptersQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetChaptersQuery, GetChaptersQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_CHAPTERS, variables, options);
|
2023-09-30 16:55:35 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-30 04:04:59 +01:00
|
|
|
public getChapters(
|
|
|
|
|
variables: GetChaptersQueryVariables,
|
|
|
|
|
options?: QueryOptions<GetChaptersQueryVariables, GetChaptersQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetChaptersQuery> {
|
|
|
|
|
return this.doRequest(GQLMethod.QUERY, GET_CHAPTERS, variables, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public useGetMangaChapters(
|
|
|
|
|
mangaId: number | string,
|
2023-09-30 16:55:35 +02:00
|
|
|
options?: QueryHookOptions<GetChaptersQuery, GetChaptersQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetChaptersQuery, GetChaptersQueryVariables> {
|
|
|
|
|
return this.useGetChapters(
|
|
|
|
|
{
|
|
|
|
|
condition: { mangaId: Number(mangaId) },
|
|
|
|
|
orderBy: ChapterOrderBy.SourceOrder,
|
|
|
|
|
orderByType: SortOrder.Desc,
|
|
|
|
|
},
|
|
|
|
|
options,
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-25 21:37:45 +01:00
|
|
|
public getMangasChapterIdsWithState(
|
|
|
|
|
mangaIds: number[],
|
|
|
|
|
states: Pick<ChapterConditionInput, 'isRead' | 'isDownloaded' | 'isBookmarked'>,
|
|
|
|
|
options?: QueryOptions<GetMangasChapterIdsWithStateQueryVariables, GetMangasChapterIdsWithStateQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<GetMangasChapterIdsWithStateQuery> {
|
2024-04-29 12:50:58 +02:00
|
|
|
return this.doRequest(
|
|
|
|
|
GQLMethod.QUERY,
|
|
|
|
|
GET_MANGAS_CHAPTER_IDS_WITH_STATE,
|
|
|
|
|
{ mangaIds, ...states },
|
|
|
|
|
{
|
|
|
|
|
fetchPolicy: 'no-cache',
|
|
|
|
|
...options,
|
|
|
|
|
},
|
|
|
|
|
);
|
2023-12-25 21:37:45 +01:00
|
|
|
}
|
|
|
|
|
|
2023-09-30 16:55:35 +02:00
|
|
|
public getMangaChaptersFetch(
|
|
|
|
|
mangaId: number | string,
|
|
|
|
|
options?: MutationOptions<GetMangaChaptersFetchMutation, GetMangaChaptersFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<GetMangaChaptersFetchMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<GetMangaChaptersFetchMutation, GetMangaChaptersFetchMutationVariables>(
|
2023-09-30 16:55:35 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
GET_MANGA_CHAPTERS_FETCH,
|
|
|
|
|
{ input: { mangaId: Number(mangaId) } },
|
2023-12-23 15:15:08 +01:00
|
|
|
{ refetchQueries: [GET_CHAPTERS], ...options },
|
2023-09-30 16:55:35 +02:00
|
|
|
);
|
2023-06-04 00:50:58 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-30 16:55:35 +02:00
|
|
|
public useGetMangaChapter(
|
2023-05-18 13:25:19 +02:00
|
|
|
mangaId: number | string,
|
|
|
|
|
chapterIndex: number | string,
|
2023-09-30 16:55:35 +02:00
|
|
|
options?: QueryHookOptions<GetChaptersQuery, GetChaptersQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<
|
|
|
|
|
Omit<GetChaptersQuery, 'chapters'> & { chapter: GetChaptersQuery['chapters']['nodes'][number] },
|
|
|
|
|
GetChaptersQueryVariables
|
|
|
|
|
> {
|
|
|
|
|
type Response = AbortableApolloUseQueryResponse<
|
|
|
|
|
Omit<GetChaptersQuery, 'chapters'> & { chapter: GetChaptersQuery['chapters']['nodes'][number] },
|
|
|
|
|
GetChaptersQueryVariables
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
const chapterResponse = this.useGetChapters(
|
|
|
|
|
{ condition: { mangaId: Number(mangaId), sourceOrder: Number(chapterIndex) } },
|
|
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!chapterResponse.data) {
|
|
|
|
|
return chapterResponse as unknown as Response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...chapterResponse,
|
|
|
|
|
data: {
|
|
|
|
|
chapter: chapterResponse.data.chapters.nodes[0],
|
|
|
|
|
},
|
|
|
|
|
} as unknown as Response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getChapter(
|
|
|
|
|
mangaId: number | string,
|
|
|
|
|
chapterIndex: number | string,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: QueryOptions<GetChaptersQueryVariables, GetChaptersQuery>,
|
2023-09-30 16:55:35 +02:00
|
|
|
): AbortabaleApolloQueryResponse<
|
|
|
|
|
Omit<GetChaptersQuery, 'chapters'> & { chapter: GetChaptersQuery['chapters']['nodes'][number] }
|
|
|
|
|
> {
|
|
|
|
|
type ResponseData = Omit<GetChaptersQuery, 'chapters'> & {
|
|
|
|
|
chapter: GetChaptersQuery['chapters']['nodes'][number];
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
const chapterRequest = this.doRequest<GetChaptersQuery, GetChaptersQueryVariables>(
|
2023-09-30 16:55:35 +02:00
|
|
|
GQLMethod.QUERY,
|
|
|
|
|
GET_CHAPTERS,
|
|
|
|
|
{
|
|
|
|
|
condition: { mangaId: Number(mangaId), sourceOrder: Number(chapterIndex) },
|
|
|
|
|
},
|
2023-10-09 20:41:58 +02:00
|
|
|
options,
|
2023-09-30 16:55:35 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...chapterRequest,
|
|
|
|
|
response: chapterRequest.response.then((chapterResponse) => {
|
|
|
|
|
if (!chapterResponse.data) {
|
|
|
|
|
return chapterResponse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...chapterResponse,
|
|
|
|
|
data: {
|
|
|
|
|
chapter: chapterResponse.data.chapters.nodes[0],
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}) as Promise<ApolloQueryResult<ResponseData>>,
|
|
|
|
|
};
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-30 16:55:35 +02:00
|
|
|
public useGetChapterPagesFetch(
|
|
|
|
|
chapterId: string | number,
|
|
|
|
|
options?: MutationHookOptions<GetChapterPagesFetchMutation, GetChapterPagesFetchMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<GetChapterPagesFetchMutation, GetChapterPagesFetchMutationVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(
|
2023-09-30 16:55:35 +02:00
|
|
|
GQLMethod.USE_MUTATION,
|
|
|
|
|
GET_CHAPTER_PAGES_FETCH,
|
|
|
|
|
{
|
|
|
|
|
input: { chapterId: Number(chapterId) },
|
|
|
|
|
},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-30 16:55:35 +02:00
|
|
|
);
|
2023-06-04 00:50:58 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public deleteDownloadedChapter(
|
|
|
|
|
id: number,
|
|
|
|
|
options?: MutationOptions<DeleteDownloadedChapterMutation, DeleteDownloadedChapterMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<DeleteDownloadedChapterMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<DeleteDownloadedChapterMutation, DeleteDownloadedChapterMutationVariables>(
|
2023-09-01 20:36:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
DELETE_DOWNLOADED_CHAPTER,
|
|
|
|
|
{ input: { id } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:36:40 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public deleteDownloadedChapters(
|
|
|
|
|
ids: number[],
|
|
|
|
|
options?: MutationOptions<DeleteDownloadedChaptersMutation, DeleteDownloadedChaptersMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<DeleteDownloadedChaptersMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<DeleteDownloadedChaptersMutation, DeleteDownloadedChaptersMutationVariables>(
|
2023-09-01 20:36:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
DELETE_DOWNLOADED_CHAPTERS,
|
|
|
|
|
{ input: { ids } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:36:40 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public updateChapter(
|
2023-09-01 20:36:40 +02:00
|
|
|
id: number,
|
2023-12-05 22:20:13 +01:00
|
|
|
patch: UpdateChapterPatchInput & {
|
|
|
|
|
chapterIdToDelete?: number;
|
2024-04-01 01:22:49 +02:00
|
|
|
trackProgressMangaId?: number;
|
2023-12-05 22:20:13 +01:00
|
|
|
},
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<UpdateChapterMutation, UpdateChapterMutationVariables>,
|
2023-09-01 20:36:40 +02:00
|
|
|
): AbortableApolloMutationResponse<UpdateChapterMutation> {
|
2024-04-01 01:22:49 +02:00
|
|
|
const { chapterIdToDelete = -1, trackProgressMangaId = -1, ...updatePatch } = patch;
|
2023-11-24 03:17:49 +01:00
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<UpdateChapterMutation, UpdateChapterMutationVariables>(
|
2023-09-01 20:36:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_CHAPTER,
|
2023-11-24 03:17:49 +01:00
|
|
|
{
|
|
|
|
|
input: { id, patch: updatePatch },
|
|
|
|
|
getBookmarked: patch.isBookmarked != null,
|
|
|
|
|
getRead: patch.isRead != null,
|
|
|
|
|
getLastPageRead: patch.lastPageRead != null,
|
2023-12-05 22:20:13 +01:00
|
|
|
chapterIdToDelete,
|
|
|
|
|
deleteChapter: chapterIdToDelete >= 0,
|
2024-04-01 01:22:49 +02:00
|
|
|
mangaId: trackProgressMangaId,
|
|
|
|
|
trackProgress: trackProgressMangaId >= 0,
|
2023-11-24 03:17:49 +01:00
|
|
|
},
|
2023-11-11 23:42:33 +01:00
|
|
|
options,
|
2023-09-01 20:36:40 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setChapterMeta(
|
2023-09-01 20:36:40 +02:00
|
|
|
chapterId: number,
|
2023-05-18 13:25:19 +02:00
|
|
|
key: string,
|
|
|
|
|
value: any,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<SetChapterMetadataMutation, SetChapterMetadataMutationVariables>,
|
2023-09-01 20:36:40 +02:00
|
|
|
): AbortableApolloMutationResponse<SetChapterMetadataMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<SetChapterMetadataMutation, SetChapterMetadataMutationVariables>(
|
2023-09-01 20:36:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
SET_CHAPTER_METADATA,
|
|
|
|
|
{ input: { meta: { chapterId, key, value: `${value}` } } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:36:40 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getChapterPageUrl(mangaId: number | string, chapterIndex: number | string, page: number): string {
|
|
|
|
|
return this.getValidImgUrlFor(
|
|
|
|
|
`manga/${mangaId}/chapter/${chapterIndex}/page/${page}`,
|
|
|
|
|
RequestManager.API_VERSION,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:36:40 +02:00
|
|
|
public updateChapters(
|
|
|
|
|
ids: number[],
|
2024-04-20 23:15:02 +02:00
|
|
|
patch: UpdateChapterPatchInput & { chapterIdsToDelete?: number[]; trackProgressMangaId?: TManga['id'] },
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<UpdateChaptersMutation, UpdateChaptersMutationVariables>,
|
2023-09-01 20:36:40 +02:00
|
|
|
): AbortableApolloMutationResponse<UpdateChaptersMutation> {
|
2024-04-20 23:15:02 +02:00
|
|
|
const { chapterIdsToDelete = [], trackProgressMangaId = -1, ...updatePatch } = patch;
|
2023-11-24 03:17:49 +01:00
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<UpdateChaptersMutation, UpdateChaptersMutationVariables>(
|
2023-09-01 20:36:40 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_CHAPTERS,
|
2023-11-24 03:17:49 +01:00
|
|
|
{
|
|
|
|
|
input: { ids, patch: updatePatch },
|
|
|
|
|
getBookmarked: patch.isBookmarked != null,
|
|
|
|
|
getRead: patch.isRead != null,
|
|
|
|
|
getLastPageRead: patch.lastPageRead != null,
|
|
|
|
|
chapterIdsToDelete,
|
|
|
|
|
deleteChapters: !!chapterIdsToDelete.length,
|
2024-04-20 23:15:02 +02:00
|
|
|
mangaId: trackProgressMangaId,
|
|
|
|
|
trackProgress: trackProgressMangaId >= 0,
|
2023-11-24 03:17:49 +01:00
|
|
|
},
|
2023-12-23 15:15:08 +01:00
|
|
|
options,
|
2023-09-01 20:36:40 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public useGetCategories(
|
|
|
|
|
options?: QueryHookOptions<GetCategoriesQuery, GetCategoriesQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetCategoriesQuery, GetCategoriesQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<GetCategoriesQuery, GetCategoriesQueryVariables>(
|
2023-10-09 20:41:58 +02:00
|
|
|
GQLMethod.USE_QUERY,
|
|
|
|
|
GET_CATEGORIES,
|
|
|
|
|
{
|
|
|
|
|
orderBy: CategoryOrderBy.Order,
|
|
|
|
|
},
|
|
|
|
|
options,
|
|
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public createCategory(
|
|
|
|
|
input: CreateCategoryInput,
|
|
|
|
|
options?: MutationOptions<CreateCategoryMutation, CreateCategoryMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<CreateCategoryMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<CreateCategoryMutation, CreateCategoryMutationVariables>(
|
2023-09-01 20:39:30 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
CREATE_CATEGORY,
|
|
|
|
|
{ input },
|
2023-10-09 20:41:58 +02:00
|
|
|
{ refetchQueries: [GET_CATEGORIES], ...options },
|
2023-09-01 20:39:30 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-16 01:38:53 +02:00
|
|
|
public useReorderCategory(
|
|
|
|
|
options?: MutationHookOptions<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables> {
|
|
|
|
|
const [mutate, result] = this.doRequest<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>(
|
|
|
|
|
GQLMethod.USE_MUTATION,
|
2023-09-01 20:39:30 +02:00
|
|
|
UPDATE_CATEGORY_ORDER,
|
2023-10-16 01:38:53 +02:00
|
|
|
undefined,
|
|
|
|
|
options,
|
2023-09-01 20:39:30 +02:00
|
|
|
);
|
2023-10-16 01:38:53 +02:00
|
|
|
|
|
|
|
|
const wrappedMutate = (mutateOptions: Parameters<typeof mutate>[0]) => {
|
|
|
|
|
const variables = mutateOptions?.variables?.input;
|
|
|
|
|
const cachedCategories = this.graphQLClient.client.readQuery<
|
|
|
|
|
GetCategoriesQuery,
|
|
|
|
|
GetCategoriesQueryVariables
|
|
|
|
|
>({
|
|
|
|
|
query: GET_CATEGORIES,
|
|
|
|
|
variables: { orderBy: CategoryOrderBy.Order },
|
|
|
|
|
})?.categories.nodes;
|
|
|
|
|
|
|
|
|
|
if (!variables) {
|
|
|
|
|
throw new Error('useReorderCategory: no variables passed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cachedCategories) {
|
|
|
|
|
throw new Error('useReorderCategory: there are no cached results');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const movedIndex = cachedCategories.findIndex((category) => category.id === variables.id);
|
|
|
|
|
const newData = [...cachedCategories.map((category) => ({ ...category }))];
|
|
|
|
|
const [removed] = newData.splice(movedIndex, 1);
|
|
|
|
|
newData.splice(variables.position, 0, removed);
|
|
|
|
|
removed.order = variables.position;
|
|
|
|
|
newData[movedIndex].order = movedIndex;
|
|
|
|
|
|
|
|
|
|
return mutate({
|
|
|
|
|
update: (cache) => {
|
|
|
|
|
cache.updateQuery<GetCategoriesQuery, GetCategoriesQueryVariables>(
|
|
|
|
|
{
|
|
|
|
|
id: cache.identify({ __typename: 'CategoryNodeList' }),
|
|
|
|
|
query: GET_CATEGORIES,
|
|
|
|
|
variables: { orderBy: CategoryOrderBy.Order },
|
|
|
|
|
},
|
|
|
|
|
(data) => ({
|
|
|
|
|
...data!,
|
|
|
|
|
categories: {
|
|
|
|
|
...data!.categories,
|
|
|
|
|
nodes: newData,
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
optimisticResponse: {
|
|
|
|
|
__typename: 'Mutation',
|
|
|
|
|
updateCategoryOrder: {
|
|
|
|
|
__typename: 'UpdateCategoryOrderPayload',
|
|
|
|
|
categories: newData,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
...mutateOptions,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return [wrappedMutate, result];
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-06 21:47:13 +02:00
|
|
|
public useGetCategoryMangas(
|
|
|
|
|
id: number,
|
2023-10-19 21:01:21 +02:00
|
|
|
options?: QueryHookOptions<GetMangasQuery, GetMangasQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetMangasQuery, GetMangasQueryVariables> {
|
2023-10-27 20:15:03 +02:00
|
|
|
const isDefaultCategory = id === 0;
|
|
|
|
|
if (isDefaultCategory) {
|
|
|
|
|
// hacky way of loading the default category mangas - some stuff won't work but since that is not used anyway, it won't be a problem
|
|
|
|
|
// can't be loaded via "useGetMangas" because mangas are not actually mapped to the default category in the database
|
|
|
|
|
const { data, ...result } = this.doRequest<GetCategoryMangasQuery, GetCategoryMangasQueryVariables>(
|
|
|
|
|
GQLMethod.USE_QUERY,
|
|
|
|
|
GET_CATEGORY_MANGAS,
|
|
|
|
|
{ id },
|
2024-04-27 22:28:55 +02:00
|
|
|
options as QueryHookOptions<GetCategoryMangasQuery, GetCategoryMangasQueryVariables>,
|
2023-10-27 20:15:03 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...result,
|
|
|
|
|
data: data
|
|
|
|
|
? {
|
|
|
|
|
...data?.category,
|
|
|
|
|
__typename: 'Query',
|
|
|
|
|
}
|
|
|
|
|
: undefined,
|
|
|
|
|
} as unknown as AbortableApolloUseQueryResponse<GetMangasQuery, GetMangasQueryVariables>;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-19 21:01:21 +02:00
|
|
|
return this.useGetMangas({ condition: { inLibrary: true, categoryIds: [id] } }, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public deleteCategory(
|
|
|
|
|
categoryId: number,
|
|
|
|
|
options?: MutationOptions<DeleteCategoryMutation, DeleteCategoryMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<DeleteCategoryMutation> {
|
2023-10-16 00:05:51 +02:00
|
|
|
const result = this.doRequest<DeleteCategoryMutation, DeleteCategoryMutationVariables>(
|
2023-09-01 20:39:30 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
DELETE_CATEGORY,
|
|
|
|
|
{ input: { categoryId } },
|
2023-10-16 00:05:51 +02:00
|
|
|
{
|
|
|
|
|
refetchQueries: [GET_CATEGORIES],
|
|
|
|
|
...options,
|
|
|
|
|
},
|
2023-09-01 20:39:30 +02:00
|
|
|
);
|
2023-10-16 00:05:51 +02:00
|
|
|
|
|
|
|
|
result.response.then(() => {
|
|
|
|
|
this.graphQLClient.client.cache.evict({ fieldName: 'category', id: categoryId.toString() });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public updateCategory(
|
2023-09-01 20:39:30 +02:00
|
|
|
id: number,
|
|
|
|
|
patch: UpdateCategoryPatchInput,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<UpdateCategoryMutation, UpdateCategoryMutationVariables>,
|
2023-09-01 20:39:30 +02:00
|
|
|
): AbortableApolloMutationResponse<UpdateCategoryMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<UpdateCategoryMutation, UpdateCategoryMutationVariables>(
|
2023-09-01 20:39:30 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_CATEGORY,
|
2023-11-24 03:17:49 +01:00
|
|
|
{
|
|
|
|
|
input: { id, patch },
|
|
|
|
|
getIncludeInUpdate: patch.includeInUpdate != null,
|
2024-01-21 13:31:04 -08:00
|
|
|
getIncludeInDownload: patch.includeInDownload != null,
|
2023-11-24 03:17:49 +01:00
|
|
|
getDefault: patch.default != null,
|
|
|
|
|
getName: patch.name != null,
|
|
|
|
|
},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:39:30 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:39:30 +02:00
|
|
|
public setCategoryMeta(
|
|
|
|
|
categoryId: number,
|
|
|
|
|
key: string,
|
|
|
|
|
value: any,
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<SetCategoryMetadataMutation, SetCategoryMetadataMutationVariables>,
|
2023-09-01 20:39:30 +02:00
|
|
|
): AbortableApolloMutationResponse<SetCategoryMetadataMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<SetCategoryMetadataMutation, SetCategoryMetadataMutationVariables>(
|
2023-09-01 20:39:30 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
SET_CATEGORY_METADATA,
|
|
|
|
|
{ input: { meta: { categoryId, key, value: `${value}` } } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:39:30 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-04 01:17:10 +02:00
|
|
|
public restoreBackupFile(
|
|
|
|
|
file: File,
|
|
|
|
|
options?: MutationOptions<RestoreBackupMutation, RestoreBackupMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<RestoreBackupMutation> {
|
2023-10-16 00:05:51 +02:00
|
|
|
const result = this.doRequest<RestoreBackupMutation, RestoreBackupMutationVariables>(
|
2023-10-04 01:17:10 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
RESTORE_BACKUP,
|
2023-10-29 01:45:08 +02:00
|
|
|
{ backup: file },
|
2023-10-16 00:05:51 +02:00
|
|
|
{
|
|
|
|
|
...options,
|
|
|
|
|
},
|
2023-10-04 01:17:10 +02:00
|
|
|
);
|
2023-10-16 00:05:51 +02:00
|
|
|
|
|
|
|
|
result.response.then(() => {
|
2024-04-10 01:23:08 +02:00
|
|
|
this.reset();
|
2023-10-16 00:05:51 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-29 01:45:08 +02:00
|
|
|
public validateBackupFile(
|
2023-05-18 13:25:19 +02:00
|
|
|
file: File,
|
2023-10-04 01:17:10 +02:00
|
|
|
options?: QueryOptions<ValidateBackupQueryVariables, ValidateBackupQuery>,
|
|
|
|
|
): AbortabaleApolloQueryResponse<ValidateBackupQuery> {
|
2023-10-29 01:45:08 +02:00
|
|
|
return this.doRequest(GQLMethod.QUERY, VALIDATE_BACKUP, { backup: file }, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-29 01:49:27 +02:00
|
|
|
public useGetBackupRestoreStatus(
|
2023-11-02 13:01:01 +01:00
|
|
|
id: string,
|
2023-10-29 01:49:27 +02:00
|
|
|
options?: QueryHookOptions<GetRestoreStatusQuery, GetRestoreStatusQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetRestoreStatusQuery, GetRestoreStatusQueryVariables> {
|
2023-11-02 13:01:01 +01:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_RESTORE_STATUS, { id }, options);
|
2023-10-29 01:49:27 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 13:25:19 +02:00
|
|
|
public getExportBackupUrl(): string {
|
|
|
|
|
return this.getValidUrlFor('backup/export/file');
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public startDownloads(
|
|
|
|
|
options?: MutationOptions<StartDownloaderMutation, StartDownloaderMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<StartDownloaderMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<StartDownloaderMutation, StartDownloaderMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
START_DOWNLOADER,
|
|
|
|
|
{},
|
2023-10-09 20:41:58 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public stopDownloads(
|
|
|
|
|
options?: MutationOptions<StopDownloaderMutation, StopDownloaderMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<StopDownloaderMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<StopDownloaderMutation, StopDownloaderMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
STOP_DOWNLOADER,
|
|
|
|
|
{},
|
2023-10-09 20:41:58 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public clearDownloads(
|
|
|
|
|
options?: MutationOptions<ClearDownloaderMutation, ClearDownloaderMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<ClearDownloaderMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<ClearDownloaderMutation, ClearDownloaderMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
CLEAR_DOWNLOADER,
|
|
|
|
|
{},
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public addChapterToDownloadQueue(
|
|
|
|
|
id: number,
|
|
|
|
|
options?: MutationOptions<EnqueueChapterDownloadMutation, EnqueueChapterDownloadMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<EnqueueChapterDownloadMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<EnqueueChapterDownloadMutation, EnqueueChapterDownloadMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
ENQUEUE_CHAPTER_DOWNLOAD,
|
|
|
|
|
{ input: { id } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public removeChapterFromDownloadQueue(
|
|
|
|
|
id: number,
|
|
|
|
|
options?: MutationOptions<DequeueChapterDownloadMutation, DequeueChapterDownloadMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<DequeueChapterDownloadMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<DequeueChapterDownloadMutation, DequeueChapterDownloadMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
DEQUEUE_CHAPTER_DOWNLOAD,
|
|
|
|
|
{ input: { id } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-13 02:05:03 +01:00
|
|
|
public useReorderChapterInDownloadQueue(
|
|
|
|
|
options?: MutationHookOptions<ReorderChapterDownloadMutation, ReorderChapterDownloadMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<ReorderChapterDownloadMutation, ReorderChapterDownloadMutationVariables> {
|
|
|
|
|
const [mutate, result] = this.doRequest(GQLMethod.USE_MUTATION, REORDER_CHAPTER_DOWNLOAD, undefined, options);
|
|
|
|
|
|
|
|
|
|
const wrappedMutate = (mutationOptions: Parameters<typeof mutate>[0]) => {
|
|
|
|
|
const variables = mutationOptions?.variables?.input;
|
|
|
|
|
const cachedDownloadStatus = this.graphQLClient.client.readFragment<
|
|
|
|
|
DownloadStatusSubscription['downloadChanged']
|
|
|
|
|
>({
|
|
|
|
|
id: 'DownloadStatus:{}',
|
|
|
|
|
fragment: FULL_DOWNLOAD_STATUS,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!variables) {
|
|
|
|
|
throw new Error('useReorderChapterInDownloadQueue: no variables passed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cachedDownloadStatus) {
|
|
|
|
|
throw new Error('useReorderChapterInDownloadQueue: there are no cached results');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const movedIndex = cachedDownloadStatus.queue.findIndex(
|
|
|
|
|
({ chapter }) => chapter.id === variables.chapterId,
|
|
|
|
|
);
|
|
|
|
|
const chapterDownload = cachedDownloadStatus.queue[movedIndex];
|
|
|
|
|
const queueWithoutChapterDownload = cachedDownloadStatus.queue.toSpliced(movedIndex, 1);
|
|
|
|
|
const updatedQueue = queueWithoutChapterDownload.toSpliced(variables.to, 0, chapterDownload);
|
|
|
|
|
|
|
|
|
|
return mutate({
|
|
|
|
|
optimisticResponse: {
|
|
|
|
|
__typename: 'Mutation',
|
|
|
|
|
reorderChapterDownload: {
|
|
|
|
|
__typename: 'ReorderChapterDownloadPayload',
|
|
|
|
|
downloadStatus: {
|
|
|
|
|
...cachedDownloadStatus,
|
|
|
|
|
queue: updatedQueue,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
...mutationOptions,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return [wrappedMutate, result];
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public addChaptersToDownloadQueue(
|
|
|
|
|
ids: number[],
|
|
|
|
|
options?: MutationOptions<EnqueueChapterDownloadsMutation, EnqueueChapterDownloadsMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<EnqueueChapterDownloadsMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<EnqueueChapterDownloadsMutation, EnqueueChapterDownloadsMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
ENQUEUE_CHAPTER_DOWNLOADS,
|
|
|
|
|
{ input: { ids } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:40:24 +02:00
|
|
|
public removeChaptersFromDownloadQueue(
|
|
|
|
|
ids: number[],
|
2023-10-09 20:41:58 +02:00
|
|
|
options?: MutationOptions<DequeueChapterDownloadsMutation, DequeueChapterDownloadsMutationVariables>,
|
2023-09-01 20:40:24 +02:00
|
|
|
): AbortableApolloMutationResponse<DequeueChapterDownloadsMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<DequeueChapterDownloadsMutation, DequeueChapterDownloadsMutationVariables>(
|
2023-09-01 20:40:24 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
DEQUEUE_CHAPTER_DOWNLOADS,
|
|
|
|
|
{ input: { ids } },
|
2023-10-16 00:05:51 +02:00
|
|
|
options,
|
2023-09-01 20:40:24 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useGetRecentlyUpdatedChapters(
|
2023-09-30 16:55:35 +02:00
|
|
|
initialPages: number = 1,
|
|
|
|
|
options?: QueryHookOptions<GetChaptersQuery, GetChaptersQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetChaptersQuery, GetChaptersQueryVariables> {
|
|
|
|
|
const PAGE_SIZE = 50;
|
|
|
|
|
const CACHE_KEY = 'useGetRecentlyUpdatedChapters';
|
|
|
|
|
|
|
|
|
|
const offset = this.cache.getResponseFor<number>(CACHE_KEY, undefined) ?? 0;
|
|
|
|
|
const [lastOffset] = useState(offset);
|
|
|
|
|
|
|
|
|
|
const result = this.useGetChapters(
|
|
|
|
|
{
|
|
|
|
|
filter: { inLibrary: { equalTo: true } },
|
|
|
|
|
orderBy: ChapterOrderBy.FetchedAt,
|
|
|
|
|
orderByType: SortOrder.Desc,
|
|
|
|
|
first: initialPages * PAGE_SIZE + lastOffset,
|
|
|
|
|
},
|
|
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...result,
|
|
|
|
|
fetchMore: (...args: Parameters<(typeof result)['fetchMore']>) => {
|
|
|
|
|
const fetchMoreOptions = args[0] ?? {};
|
|
|
|
|
this.cache.cacheResponse(CACHE_KEY, undefined, fetchMoreOptions.variables?.offset);
|
|
|
|
|
return result.fetchMore({
|
|
|
|
|
...fetchMoreOptions,
|
|
|
|
|
variables: { first: PAGE_SIZE, ...fetchMoreOptions.variables },
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
} as typeof result;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public startGlobalUpdate(
|
|
|
|
|
categories?: undefined,
|
|
|
|
|
options?: MutationOptions<UpdateLibraryMangasMutation, UpdateLibraryMangasMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateLibraryMangasMutation>;
|
2023-09-01 20:40:39 +02:00
|
|
|
|
|
|
|
|
public startGlobalUpdate(
|
2023-10-09 20:41:58 +02:00
|
|
|
categories: number[],
|
|
|
|
|
options?: MutationOptions<UpdateCategoryMangasMutation, UpdateCategoryMangasMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<UpdateCategoryMangasMutation>;
|
|
|
|
|
|
|
|
|
|
public startGlobalUpdate<
|
|
|
|
|
Data extends UpdateLibraryMangasMutation | UpdateCategoryMangasMutation,
|
|
|
|
|
Variables extends UpdateLibraryMangasMutationVariables | UpdateCategoryMangasMutationVariables,
|
|
|
|
|
>(categories?: number[], options?: MutationOptions<Data, Variables>): AbortableApolloMutationResponse<Data> {
|
2023-09-01 20:40:39 +02:00
|
|
|
if (categories?.length) {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<UpdateCategoryMangasMutation, UpdateCategoryMangasMutationVariables>(
|
2023-09-01 20:40:39 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_CATEGORY_MANGAS,
|
|
|
|
|
{ input: { categories } },
|
2023-10-09 20:41:58 +02:00
|
|
|
options as MutationOptions<UpdateCategoryMangasMutation, UpdateCategoryMangasMutationVariables>,
|
|
|
|
|
) as AbortableApolloMutationResponse<Data>;
|
2023-09-01 20:40:39 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<UpdateLibraryMangasMutation, UpdateLibraryMangasMutationVariables>(
|
2023-09-01 20:40:39 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
UPDATE_LIBRARY_MANGAS,
|
|
|
|
|
{},
|
2023-10-09 20:41:58 +02:00
|
|
|
options as MutationOptions<UpdateLibraryMangasMutation, UpdateLibraryMangasMutationVariables>,
|
|
|
|
|
) as AbortableApolloMutationResponse<Data>;
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 20:41:58 +02:00
|
|
|
public resetGlobalUpdate(
|
|
|
|
|
options?: MutationOptions<StopUpdaterMutation, StopUpdaterMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<StopUpdaterMutation> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest<StopUpdaterMutation, StopUpdaterMutationVariables>(
|
2023-09-01 20:40:39 +02:00
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
STOP_UPDATER,
|
|
|
|
|
{},
|
2023-10-09 20:41:58 +02:00
|
|
|
options,
|
2023-09-01 20:40:39 +02:00
|
|
|
);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-01 20:40:39 +02:00
|
|
|
public useGetGlobalUpdateSummary(
|
|
|
|
|
options?: QueryHookOptions<GetUpdateStatusQuery, GetUpdateStatusQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetUpdateStatusQuery, GetUpdateStatusQueryVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_UPDATE_STATUS, {}, options);
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
2023-10-04 22:34:32 +02:00
|
|
|
|
2023-12-13 02:05:03 +01:00
|
|
|
public useGetDownloadStatus(
|
2024-01-01 22:40:39 +01:00
|
|
|
options?: QueryHookOptions<GetDownloadStatusQuery, GetDownloadStatusQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetDownloadStatusQuery, GetDownloadStatusQueryVariables> {
|
2023-12-13 02:05:03 +01:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_DOWNLOAD_STATUS, {}, options);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-04 22:34:32 +02:00
|
|
|
public useDownloadSubscription(
|
|
|
|
|
options?: SubscriptionHookOptions<DownloadStatusSubscription, DownloadStatusSubscriptionVariables>,
|
|
|
|
|
): SubscriptionResult<DownloadStatusSubscription, DownloadStatusSubscriptionVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_SUBSCRIPTION, DOWNLOAD_STATUS_SUBSCRIPTION, {}, options);
|
2023-10-04 22:34:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useUpdaterSubscription(
|
|
|
|
|
options?: SubscriptionHookOptions<UpdaterSubscription, UpdaterSubscriptionVariables>,
|
|
|
|
|
): SubscriptionResult<UpdaterSubscription, UpdaterSubscriptionVariables> {
|
2023-10-15 21:01:46 +02:00
|
|
|
return this.doRequest(GQLMethod.USE_SUBSCRIPTION, UPDATER_SUBSCRIPTION, {}, options);
|
2023-10-04 22:34:32 +02:00
|
|
|
}
|
2023-10-27 23:39:05 +02:00
|
|
|
|
|
|
|
|
public useGetServerSettings(
|
|
|
|
|
options?: QueryHookOptions<GetServerSettingsQuery, GetSourcesQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetServerSettingsQuery, GetSourcesQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_SERVER_SETTINGS, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useUpdateServerSettings(
|
|
|
|
|
options?: MutationHookOptions<UpdateServerSettingsMutation, UpdateServerSettingsMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<UpdateServerSettingsMutation, UpdateServerSettingsMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, UPDATE_SERVER_SETTINGS, undefined, options);
|
|
|
|
|
}
|
2023-11-19 21:17:35 +01:00
|
|
|
|
2023-11-19 22:43:29 +01:00
|
|
|
public useGetLastGlobalUpdateTimestamp(
|
|
|
|
|
options?: QueryHookOptions<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetLastUpdateTimestampQuery, GetLastUpdateTimestampQueryVariables> {
|
2023-11-25 15:35:36 +01:00
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_LAST_UPDATE_TIMESTAMP, {}, options);
|
2023-11-19 22:43:29 +01:00
|
|
|
}
|
2023-12-09 14:16:52 +01:00
|
|
|
|
|
|
|
|
public useClearServerCache(
|
2024-04-27 00:03:37 +02:00
|
|
|
input: ClearCachedImagesInput = { cachedPages: true, cachedThumbnails: true },
|
2023-12-09 14:16:52 +01:00
|
|
|
options?: MutationHookOptions<ClearServerCacheMutation, ClearServerCacheMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<ClearServerCacheMutation, ClearServerCacheMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, CLEAR_SERVER_CACHE, { input }, options);
|
|
|
|
|
}
|
2023-12-09 23:08:27 +01:00
|
|
|
|
|
|
|
|
public useWebUIUpdateSubscription(
|
|
|
|
|
options?: SubscriptionHookOptions<WebuiUpdateSubscription, WebuiUpdateSubscription>,
|
|
|
|
|
): SubscriptionResult<WebuiUpdateSubscription, WebuiUpdateSubscription> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_SUBSCRIPTION, WEBUI_UPDATE_SUBSCRIPTION, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public resetWebUIUpdateStatus(
|
|
|
|
|
options?: MutationOptions<ResetWebuiUpdateStatusMutation, ResetWebuiUpdateStatusMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<ResetWebuiUpdateStatusMutation> {
|
|
|
|
|
return this.doRequest(GQLMethod.MUTATION, RESET_WEBUI_UPDATE_STATUS, undefined, options);
|
|
|
|
|
}
|
2024-01-01 22:40:39 +01:00
|
|
|
|
|
|
|
|
public useGetWebUIUpdateStatus(
|
|
|
|
|
options?: QueryHookOptions<GetWebuiUpdateStatusQuery, GetWebuiUpdateStatusQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetWebuiUpdateStatusQuery, GetWebuiUpdateStatusQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_WEBUI_UPDATE_STATUS, undefined, options);
|
|
|
|
|
}
|
2024-01-26 20:50:51 +01:00
|
|
|
|
|
|
|
|
public useGetMigratableSources(
|
|
|
|
|
options?: QueryHookOptions<GetMigratableSourcesQuery, GetMigratableSourcesQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetMigratableSourcesQuery, GetMigratableSourcesQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_MIGRATABLE_SOURCES, undefined, options);
|
|
|
|
|
}
|
2024-02-16 19:55:54 +01:00
|
|
|
|
|
|
|
|
public useGetTrackerList(
|
|
|
|
|
options?: QueryHookOptions<GetTrackersQuery, GetTrackersQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<GetTrackersQuery, GetTrackersQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, GET_TRACKERS, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useLogoutFromTracker(
|
|
|
|
|
options?: MutationHookOptions<TrackerLogoutMutation, TrackerLogoutMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<TrackerLogoutMutation, TrackerLogoutMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, TRACKER_LOGOUT, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useLoginToTrackerOauth(
|
|
|
|
|
options?: MutationHookOptions<TrackerLoginOauthMutation, TrackerLoginOauthMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<TrackerLoginOauthMutation, TrackerLoginOauthMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, TRACKER_LOGIN_OAUTH, undefined, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useLoginToTrackerCredentials(
|
|
|
|
|
options?: MutationHookOptions<TrackerLoginCredentialsMutation, TrackerLoginCredentialsMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<TrackerLoginCredentialsMutation, TrackerLoginCredentialsMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, TRACKER_LOGIN_CREDENTIALS, undefined, options);
|
|
|
|
|
}
|
2024-03-10 17:36:22 +01:00
|
|
|
|
|
|
|
|
public useTrackerSearch(
|
|
|
|
|
trackerId: number,
|
|
|
|
|
query: string,
|
|
|
|
|
options?: QueryHookOptions<TrackerSearchQuery, TrackerSearchQueryVariables>,
|
|
|
|
|
): AbortableApolloUseQueryResponse<TrackerSearchQuery, TrackerSearchQueryVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_QUERY, TRACKER_SEARCH, { trackerId, query }, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public useBindTracker(
|
|
|
|
|
options?: MutationHookOptions<TrackerBindMutation, TrackerBindMutationVariables>,
|
|
|
|
|
): AbortableApolloUseMutationResponse<TrackerBindMutation, TrackerBindMutationVariables> {
|
|
|
|
|
return this.doRequest(GQLMethod.USE_MUTATION, TRACKER_BIND, undefined, options);
|
|
|
|
|
}
|
2024-03-17 18:42:48 +01:00
|
|
|
|
2024-04-20 23:51:47 +02:00
|
|
|
public bindTracker(
|
|
|
|
|
mangaId: number,
|
|
|
|
|
trackerId: number,
|
|
|
|
|
remoteId: string,
|
|
|
|
|
options?: MutationOptions<TrackerBindMutation, TrackerBindMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<TrackerBindMutation> {
|
|
|
|
|
return this.doRequest(GQLMethod.MUTATION, TRACKER_BIND, { mangaId, remoteId, trackerId }, options);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-01 00:45:44 +02:00
|
|
|
public unbindTracker(
|
|
|
|
|
recordId: number,
|
|
|
|
|
deleteRemoteTrack?: boolean,
|
|
|
|
|
options?: MutationHookOptions<TrackerUnbindMutation, TrackerUnbindMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<TrackerUnbindMutation> {
|
|
|
|
|
return this.doRequest<TrackerUnbindMutation, TrackerUnbindMutationVariables>(
|
|
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
TRACKER_UNBIND,
|
|
|
|
|
{ input: { recordId, deleteRemoteTrack } },
|
|
|
|
|
{ refetchQueries: [GET_MANGA, GET_CATEGORY_MANGAS, GET_MANGAS], ...options },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:42:48 +01:00
|
|
|
public updateTrackerBind(
|
|
|
|
|
id: number,
|
|
|
|
|
patch: Omit<UpdateTrackInput, 'clientMutationId' | 'recordId'>,
|
|
|
|
|
options?: MutationOptions<TrackerUpdateBindMutation, TrackerUpdateBindMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<TrackerUpdateBindMutation> {
|
2024-04-01 00:45:44 +02:00
|
|
|
return this.doRequest(GQLMethod.MUTATION, TRACKER_UPDATE_BIND, { input: { ...patch, recordId: id } }, options);
|
2024-03-17 18:42:48 +01:00
|
|
|
}
|
2024-04-01 02:06:35 +02:00
|
|
|
|
|
|
|
|
public fetchTrackBind(
|
|
|
|
|
recordId: number,
|
|
|
|
|
options?: MutationOptions<TrackerFetchBindMutation, TrackerFetchBindMutationVariables>,
|
|
|
|
|
): AbortableApolloMutationResponse<TrackerFetchBindMutation> {
|
|
|
|
|
return this.doRequest<TrackerFetchBindMutation, TrackerFetchBindMutationVariables>(
|
|
|
|
|
GQLMethod.MUTATION,
|
|
|
|
|
TRACKER_FETCH_BIND,
|
|
|
|
|
{ recordId },
|
|
|
|
|
options,
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-05-18 13:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-28 00:32:02 +02:00
|
|
|
export const requestManager = new RequestManager();
|