Reduce requested source data in queries
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import gql from 'graphql-tag';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
@@ -21,6 +20,9 @@ import { GridLayouts } from '@/components/source/GridLayouts.tsx';
|
||||
import { useLocalStorage } from '@/util/useStorage.tsx';
|
||||
import { GridLayout } from '@/components/context/LibraryOptionsContext.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { GetSourceMigratableQuery, GetSourceMigratableQueryVariables } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { GET_SOURCE_MIGRATABLE } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||
import { SOURCE_BASE_FIELDS } from '@/lib/graphql/fragments/SourceFragments.ts';
|
||||
|
||||
export const Migrate = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -34,12 +36,7 @@ export const Migrate = () => {
|
||||
Pick<TMigratableSource, 'id' | 'name'>
|
||||
>({
|
||||
id: requestManager.graphQLClient.client.cache.identify({ __typename: 'SourceType', id: paramSourceId }),
|
||||
fragment: gql`
|
||||
fragment MigratableSource on SourceType {
|
||||
id
|
||||
name
|
||||
}
|
||||
`,
|
||||
fragment: SOURCE_BASE_FIELDS,
|
||||
});
|
||||
|
||||
const [isKnownSource, setIsKnownSource] = useState(fragmentSource !== null ? true : undefined);
|
||||
@@ -48,7 +45,11 @@ export const Migrate = () => {
|
||||
loading: isSourceLoading,
|
||||
error: sourceError,
|
||||
refetch: refetchSource,
|
||||
} = requestManager.useGetSource(paramSourceId, { skip: !!isKnownSource, notifyOnNetworkStatusChange: true });
|
||||
} = requestManager.useGetSource<GetSourceMigratableQuery, GetSourceMigratableQueryVariables>(
|
||||
GET_SOURCE_MIGRATABLE,
|
||||
paramSourceId,
|
||||
{ skip: !!isKnownSource, notifyOnNetworkStatusChange: true },
|
||||
);
|
||||
|
||||
const { sourceId, name } = {
|
||||
sourceId: paramSourceId,
|
||||
|
||||
@@ -13,7 +13,6 @@ import React, { useCallback, useContext, useEffect, useMemo, useState } from 're
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { StringParam, useQueryParam } from 'use-query-params';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ISource } from '@/typings';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { useLocalStorage } from '@/util/useStorage.tsx';
|
||||
import { langSortCmp, sourceDefualtLangs, sourceForcedDefaultLangs } from '@/util/language';
|
||||
@@ -28,11 +27,12 @@ import { EmptyView } from '@/components/util/EmptyView';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
||||
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
||||
|
||||
function sourceToLangList(sources: ISource[]) {
|
||||
function sourceToLangList(sources: Pick<SourceType, 'lang'>[]) {
|
||||
const result: string[] = [];
|
||||
|
||||
sources.forEach((source) => {
|
||||
@@ -45,7 +45,10 @@ function sourceToLangList(sources: ISource[]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const compareSourceByName = (sourceA: ISource, sourceB: ISource): -1 | 0 | 1 => {
|
||||
const compareSourceByName = (
|
||||
sourceA: Pick<SourceType, 'displayName'>,
|
||||
sourceB: Pick<SourceType, 'displayName'>,
|
||||
): -1 | 0 | 1 => {
|
||||
if (sourceA.displayName < sourceB.displayName) {
|
||||
return -1;
|
||||
}
|
||||
@@ -56,8 +59,8 @@ const compareSourceByName = (sourceA: ISource, sourceB: ISource): -1 | 0 | 1 =>
|
||||
};
|
||||
|
||||
const compareSourcesBySearchResult = (
|
||||
sourceA: ISource,
|
||||
sourceB: ISource,
|
||||
sourceA: Pick<SourceType, 'id'>,
|
||||
sourceB: Pick<SourceType, 'id'>,
|
||||
sourceToFetchedStateMap: SourceToLoadingStateMap,
|
||||
): -1 | 0 | 1 => {
|
||||
const isSourceAFetched = !sourceToFetchedStateMap.get(sourceA.id)?.isLoading;
|
||||
@@ -93,9 +96,9 @@ const SourceSearchPreview = React.memo(
|
||||
emptyQuery,
|
||||
mode,
|
||||
}: {
|
||||
source: ISource;
|
||||
source: Pick<SourceType, 'id' | 'displayName' | 'lang'>;
|
||||
onSearchRequestFinished: (
|
||||
source: ISource,
|
||||
source: Pick<SourceType, 'id'>,
|
||||
isLoading: boolean,
|
||||
hasResults: boolean,
|
||||
emptySearch: boolean,
|
||||
@@ -130,9 +133,7 @@ const SourceSearchPreview = React.memo(
|
||||
// INFO:
|
||||
// with strict mode + dev mode the first request will be aborted. due to using SWR there won't be an
|
||||
// immediate second request since it's the same key. instead the "second" request will be the error handling of SWR
|
||||
abortRequest(
|
||||
new Error(`SourceSearchPreview(${source.id}, ${source.displayName}): search string changed`),
|
||||
);
|
||||
abortRequest(new Error(`SourceSearchPreview(${id}, ${displayName}): search string changed`));
|
||||
},
|
||||
[searchString],
|
||||
);
|
||||
@@ -221,7 +222,7 @@ export const SearchAll: React.FC = () => {
|
||||
);
|
||||
|
||||
const updateSourceLoadingState = useCallback(
|
||||
({ id }: ISource, isLoading: boolean, hasResults: boolean, emptySearch: boolean) => {
|
||||
({ id }: Pick<SourceType, 'id'>, isLoading: boolean, hasResults: boolean, emptySearch: boolean) => {
|
||||
setSourceToLoadingStateMap((currentMap) => {
|
||||
const mapCopy = new Map(currentMap);
|
||||
mapCopy.set(id, { isLoading, hasResults, emptySearch });
|
||||
|
||||
@@ -21,6 +21,8 @@ import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { GetCategoriesSettingsQueryVariables, GetSourceSettingsQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { GET_SOURCE_SETTINGS } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||
|
||||
function getPrefComponent(type: string) {
|
||||
switch (type) {
|
||||
@@ -54,7 +56,10 @@ export function SourceConfigure() {
|
||||
}, [t]);
|
||||
|
||||
const { sourceId } = useParams<{ sourceId: string }>();
|
||||
const { data, loading, error, refetch } = requestManager.useGetSource(sourceId, {
|
||||
const { data, loading, error, refetch } = requestManager.useGetSource<
|
||||
GetSourceSettingsQuery,
|
||||
GetCategoriesSettingsQueryVariables
|
||||
>(GET_SOURCE_SETTINGS, sourceId, {
|
||||
notifyOnNetworkStatusChange: true,
|
||||
});
|
||||
const sourcePreferences = data?.source.preferences ?? [];
|
||||
|
||||
@@ -20,7 +20,7 @@ import { styled } from '@mui/material/styles';
|
||||
import FavoriteIcon from '@mui/icons-material/Favorite';
|
||||
import NewReleasesIcon from '@mui/icons-material/NewReleases';
|
||||
import FilterListIcon from '@mui/icons-material/FilterList';
|
||||
import { IPos, TPartialManga, TPartialSource, TranslationKey } from '@/typings';
|
||||
import { IPos, TPartialManga, TranslationKey } from '@/typings';
|
||||
import {
|
||||
requestManager,
|
||||
AbortableApolloUseMutationPaginatedResponse,
|
||||
@@ -32,6 +32,8 @@ import { AppbarSearch } from '@/components/util/AppbarSearch';
|
||||
import { SourceOptions } from '@/components/source/SourceOptions';
|
||||
import { SourceMangaGrid } from '@/components/source/SourceMangaGrid';
|
||||
import {
|
||||
GetSourceBrowseQuery,
|
||||
GetSourceBrowseQueryVariables,
|
||||
GetSourceMangasFetchMutation,
|
||||
GetSourceMangasFetchMutationVariables,
|
||||
} from '@/lib/graphql/generated/graphql.ts';
|
||||
@@ -42,6 +44,7 @@ import { AppStorage } from '@/util/AppStorage.ts';
|
||||
import { getGridSnapshotKey } from '@/components/MangaGrid.tsx';
|
||||
import { createUpdateSourceMetadata, getSourceMetadata } from '@/lib/metadata/sourceMetadata.ts';
|
||||
import { makeToast } from '@/components/util/Toast.tsx';
|
||||
import { GET_SOURCE_BROWSE } from '@/lib/graphql/queries/SourceQuery.ts';
|
||||
|
||||
const ContentTypeMenu = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
@@ -280,14 +283,16 @@ export function SourceMangas() {
|
||||
const isLoading = loading || filteredOutAllItemsOfFetchedPage;
|
||||
const mangas = data?.fetchSourceManga?.mangas ?? [];
|
||||
const hasNextPage = !!data?.fetchSourceManga?.hasNextPage;
|
||||
const { data: sourceData } = requestManager.useGetSource(sourceId);
|
||||
const { data: sourceData } = requestManager.useGetSource<GetSourceBrowseQuery, GetSourceBrowseQueryVariables>(
|
||||
GET_SOURCE_BROWSE,
|
||||
sourceId,
|
||||
);
|
||||
const source = sourceData?.source;
|
||||
|
||||
const filters = source?.filters ?? [];
|
||||
const { savedSearches = {} } = useMemo(() => getSourceMetadata(source), [source, source?.meta]);
|
||||
const updateSourceMetadata = createUpdateSourceMetadata<'savedSearches'>(
|
||||
source ?? ({ id: sourceId } as TPartialSource),
|
||||
() => makeToast(t('global.error.label.failed_to_save_changes'), 'error'),
|
||||
const updateSourceMetadata = createUpdateSourceMetadata<'savedSearches'>(source ?? { id: sourceId }, () =>
|
||||
makeToast(t('global.error.label.failed_to_save_changes'), 'error'),
|
||||
);
|
||||
|
||||
const selectSavedSearch = useCallback(
|
||||
|
||||
@@ -13,7 +13,6 @@ import Typography from '@mui/material/Typography';
|
||||
import TravelExploreIcon from '@mui/icons-material/TravelExplore';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ISource, TPartialSource } from '@/typings';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { useLocalStorage } from '@/util/useStorage.tsx';
|
||||
import { sourceDefualtLangs, sourceForcedDefaultLangs, langSortCmp } from '@/util/language';
|
||||
@@ -24,8 +23,9 @@ import { LangSelect } from '@/components/navbar/action/LangSelect';
|
||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
function sourceToLangList(sources: ISource[]) {
|
||||
function sourceToLangList(sources: Pick<SourceType, 'lang'>[]) {
|
||||
const result: string[] = [];
|
||||
|
||||
sources.forEach((source) => {
|
||||
@@ -38,11 +38,11 @@ function sourceToLangList(sources: ISource[]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function groupByLang(sources: ISource[]) {
|
||||
const result = {} as any;
|
||||
function groupByLang<Source extends Pick<SourceType, 'lang'>>(sources: Source[]): Record<string, Source[]> {
|
||||
const result: Record<string, Source[]> = {};
|
||||
sources.forEach((source) => {
|
||||
if (result[source.lang] === undefined) {
|
||||
result[source.lang] = [] as ISource[];
|
||||
result[source.lang] = [];
|
||||
}
|
||||
result[source.lang].push(source);
|
||||
});
|
||||
@@ -150,7 +150,7 @@ export function Sources() {
|
||||
>
|
||||
{translateExtensionLanguage(lang)}
|
||||
</Typography>
|
||||
{(list as TPartialSource[])
|
||||
{list
|
||||
.filter((source) => showNsfw || !source.isNsfw)
|
||||
.map((source) => (
|
||||
<SourceCard
|
||||
|
||||
Reference in New Issue
Block a user