Reduce requested manga data in queries

This commit is contained in:
schroda
2024-07-08 18:02:50 +02:00
parent 4b30e9bc48
commit 3d21266f92
47 changed files with 759 additions and 471 deletions

View File

@@ -19,8 +19,14 @@ import SyncAltIcon from '@mui/icons-material/SyncAlt';
import { Link } from 'react-router-dom';
import SyncIcon from '@mui/icons-material/Sync';
import Dialog from '@mui/material/Dialog';
import { TManga } from '@/typings.ts';
import { actionToTranslationKey, MangaAction, MangaDownloadInfo, Mangas, MangaUnreadInfo } from '@/lib/data/Mangas.ts';
import {
actionToTranslationKey,
MangaAction,
MangaDownloadInfo,
MangaIdInfo,
Mangas,
MangaUnreadInfo,
} from '@/lib/data/Mangas.ts';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { MenuItem } from '@/components/menu/MenuItem.tsx';
import { createGetMenuItemTitle, createIsMenuItemDisabled, createShouldShowMenuItem } from '@/components/menu/util.ts';
@@ -29,18 +35,19 @@ import { TrackManga } from '@/components/tracker/TrackManga.tsx';
import { useCategorySelect } from '@/components/navbar/action/useCategorySelect.tsx';
import { ChaptersDownloadActionMenuItems } from '@/components/chapter/ChaptersDownloadActionMenuItems.tsx';
import { NestedMenuItem } from '@/components/menu/NestedMenuItem.tsx';
import { MangaChapterStatFieldsFragment, MangaType } from '@/lib/graphql/generated/graphql.ts';
const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const;
type BaseProps = { onClose: (selectionModeState: boolean) => void; setHideMenu: (hide: boolean) => void };
export type SingleModeProps = {
manga: Pick<TManga, 'id' | 'title' | 'source' | 'trackRecords'> & MangaDownloadInfo & MangaUnreadInfo;
handleSelection?: SelectableCollectionReturnType<TManga['id']>['handleSelection'];
manga: Pick<MangaType, 'id' | 'title' | 'sourceId'> & MangaDownloadInfo & MangaUnreadInfo;
handleSelection?: SelectableCollectionReturnType<MangaType['id']>['handleSelection'];
};
type SelectModeProps = {
selectedMangas: TManga[];
selectedMangas: MangaChapterStatFieldsFragment[];
};
type Props =
@@ -82,7 +89,7 @@ export const MangaActionMenuItems = ({
onClose(true);
};
const performAction = (action: MangaAction, mangas: TManga[]) => {
const performAction = (action: MangaAction, mangas: MangaIdInfo[]) => {
Mangas.performAction(action, manga ? [manga.id] : Mangas.getIds(mangas), {
wasManuallyMarkedAsRead: true,
}).catch(defaultPromiseErrorHandler(`MangaActionMenuItems:performAction(${action})`));
@@ -150,7 +157,7 @@ export const MangaActionMenuItems = ({
)}
{isSingleMode && (
<Link
to={`/migrate/source/${manga?.source?.id}/manga/${manga?.id}/search?query=${manga?.title}`}
to={`/migrate/source/${manga?.sourceId}/manga/${manga?.id}/search?query=${manga?.title}`}
state={{ mangaTitle: manga?.title }}
style={{ textDecoration: 'none', color: 'inherit' }}
>

View File

@@ -8,24 +8,37 @@
import { LongPressPointerHandlers, LongPressResult } from 'use-long-press/lib/use-long-press.types';
import { PopupState } from 'material-ui-popup-state/hooks';
import { TManga, TPartialManga } from '@/typings.ts';
import { GridLayout } from '@/components/context/LibraryOptionsContext.tsx';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { useManageMangaLibraryState } from '@/components/manga/useManageMangaLibraryState.tsx';
import { MangaChapterCountInfo, MangaThumbnailInfo } from '@/lib/data/Mangas.ts';
import { ChapterType, MangaType } from '@/lib/graphql/generated/graphql.ts';
import { SingleModeProps } from '@/components/manga/MangaActionMenuItems.tsx';
export type MangaCardMode = 'default' | 'source' | 'migrate.search' | 'migrate.select' | 'duplicate';
type MangaCardBaseProps = Pick<MangaType, 'id' | 'title' | 'sourceId'> &
SingleModeProps['manga'] &
Partial<Pick<MangaType, 'inLibrary' | 'downloadCount' | 'unreadCount'>> &
MangaChapterCountInfo & {
latestReadChapter?: Pick<ChapterType, 'id' | 'sourceOrder'> | null;
firstUnreadChapter?: Pick<ChapterType, 'id' | 'sourceOrder'> | null;
};
type MangaCardSpecificProps = MangaCardBaseProps & MangaThumbnailInfo;
export interface MangaCardProps {
manga: TPartialManga;
manga: MangaCardBaseProps;
gridLayout?: GridLayout;
inLibraryIndicator?: boolean;
selected?: boolean | null;
handleSelection?: SelectableCollectionReturnType<TManga['id']>['handleSelection'];
handleSelection?: SelectableCollectionReturnType<MangaType['id']>['handleSelection'];
mode?: MangaCardMode;
}
export type SpecificMangaCardProps = MangaCardProps &
export type SpecificMangaCardProps = Omit<MangaCardProps, 'manga'> &
Pick<ReturnType<typeof useManageMangaLibraryState>, 'isInLibrary'> & {
manga: MangaCardSpecificProps;
longPressBind: LongPressResult<LongPressPointerHandlers>;
popupState: PopupState;
handleClick: (event: React.MouseEvent | React.TouchEvent) => void;

View File

@@ -10,22 +10,21 @@ import FavoriteIcon from '@mui/icons-material/Favorite';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import PublicIcon from '@mui/icons-material/Public';
import { styled } from '@mui/material/styles';
import React, { ComponentProps, useEffect, useMemo } from 'react';
import { ComponentProps, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { t as translate } from 'i18next';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import { useLongPress } from 'use-long-press';
import { TManga } from '@/typings';
import { makeToast } from '@/components/util/Toast';
import { Mangas } from '@/lib/data/Mangas.ts';
import { Mangas, MangaThumbnailInfo, MangaTrackRecordInfo } from '@/lib/data/Mangas.ts';
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
import { CustomIconButton } from '@/components/atoms/CustomIconButton';
import { TrackMangaButton } from '@/components/manga/TrackMangaButton.tsx';
import { useManageMangaLibraryState } from '@/components/manga/useManageMangaLibraryState.tsx';
import { Metadata as BaseMetadata } from '@/components/atoms/Metadata.tsx';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { SourceType } from '@/lib/graphql/generated/graphql.ts';
import { MangaType, SourceType } from '@/lib/graphql/generated/graphql.ts';
const DetailsWrapper = styled('div')(({ theme }) => ({
width: '100%',
@@ -156,10 +155,6 @@ const OpenSourceButton = ({ url }: { url?: string | null }) => {
return button;
};
interface IProps {
manga: TManga;
}
function getSourceName(source?: Pick<SourceType, 'id' | 'displayName'> | null): string {
if (!source) {
return translate('global.label.unknown');
@@ -172,7 +167,18 @@ function getValueOrUnknown(val?: string | null) {
return val ?? translate('global.label.unknown');
}
export const MangaDetails: React.FC<IProps> = ({ manga }) => {
export const MangaDetails = ({
manga,
}: {
manga: Pick<
MangaType,
'id' | 'title' | 'author' | 'artist' | 'status' | 'inLibrary' | 'realUrl' | 'description' | 'genre'
> &
MangaThumbnailInfo &
MangaTrackRecordInfo & {
source?: Pick<SourceType, 'id' | 'displayName'> | null;
};
}) => {
const { t } = useTranslation();
useEffect(() => {

View File

@@ -16,8 +16,8 @@ import MoreVertIcon from '@mui/icons-material/MoreVert';
import { PopupState } from 'material-ui-popup-state/hooks';
import { bindTrigger } from 'material-ui-popup-state';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { TManga } from '@/typings.ts';
import { MediaQuery } from '@/lib/ui/MediaQuery.tsx';
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
export const MangaOptionButton = forwardRef(
(
@@ -30,7 +30,7 @@ export const MangaOptionButton = forwardRef(
}: {
id: number;
selected?: boolean | null;
handleSelection?: SelectableCollectionReturnType<TManga['id']>['handleSelection'];
handleSelection?: SelectableCollectionReturnType<MangaType['id']>['handleSelection'];
asCheckbox?: boolean;
popupState: PopupState;
},

View File

@@ -21,11 +21,11 @@ import { Link } from 'react-router-dom';
import SyncAltIcon from '@mui/icons-material/SyncAlt';
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
import { TManga } from '@/typings.ts';
import { useCategorySelect } from '@/components/navbar/action/useCategorySelect.tsx';
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
interface IProps {
manga: TManga;
manga: Pick<MangaType, 'id' | 'inLibrary' | 'sourceId' | 'title'>;
onRefresh: () => any;
refreshing: boolean;
}
@@ -64,7 +64,7 @@ export const MangaToolbarMenu = ({ manga, onRefresh, refreshing }: IProps) => {
<>
<Tooltip title={t('global.button.migrate')}>
<Link
to={`/migrate/source/${manga.source?.id}/manga/${manga.id}/search?query=${manga.title}`}
to={`/migrate/source/${manga.sourceId}/manga/${manga.id}/search?query=${manga.title}`}
state={{ mangaTitle: manga.title }}
style={{ textDecoration: 'none', color: 'inherit' }}
>
@@ -122,7 +122,7 @@ export const MangaToolbarMenu = ({ manga, onRefresh, refreshing }: IProps) => {
<MenuItem
key="migrate"
component={Link}
to={`/migrate/source/${manga.source?.id}/manga/${manga.id}/search?query=${manga.title}`}
to={`/migrate/source/${manga.sourceId}/manga/${manga.id}/search?query=${manga.title}`}
state={{ mangaTitle: manga.title }}
style={{ textDecoration: 'none', color: 'inherit' }}
>

View File

@@ -16,20 +16,21 @@ import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { TrackManga } from '@/components/tracker/TrackManga.tsx';
import { Trackers } from '@/lib/data/Trackers.ts';
import { TManga } from '@/typings.ts';
import { CustomIconButton } from '@/components/atoms/CustomIconButton.tsx';
import { GetTrackersSettingsQuery } from '@/lib/graphql/generated/graphql.ts';
import { GetTrackersSettingsQuery, MangaType } from '@/lib/graphql/generated/graphql.ts';
import { GET_TRACKERS_SETTINGS } from '@/lib/graphql/queries/TrackerQuery.ts';
import { MangaTrackRecordInfo } from '@/lib/data/Mangas.ts';
export const TrackMangaButton = ({ manga }: { manga: TManga }) => {
export const TrackMangaButton = ({ manga }: { manga: MangaTrackRecordInfo & Pick<MangaType, 'title'> }) => {
const { t } = useTranslation();
const navigate = useNavigate();
const trackerList = requestManager.useGetTrackerList<GetTrackersSettingsQuery>(GET_TRACKERS_SETTINGS);
const trackers = trackerList.data?.trackers.nodes ?? [];
const mangaTrackers = manga.trackRecords.nodes;
const loggedInTrackers = Trackers.getLoggedIn(trackerList.data?.trackers.nodes ?? []);
const trackersInUse = Trackers.getLoggedIn(Trackers.getTrackers(mangaTrackers));
const loggedInTrackers = Trackers.getLoggedIn(trackers);
const trackersInUse = Trackers.getLoggedIn(Trackers.getTrackers(mangaTrackers, trackers));
const handleClick = (openPopup: () => void) => {
if (trackerList.error) {

View File

@@ -16,19 +16,18 @@ import { getMetadataServerSettings } from '@/lib/metadata/metadataServerSettings
import { Categories } from '@/lib/data/Categories.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { Mangas } from '@/lib/data/Mangas.ts';
import { TManga } from '@/typings.ts';
import { awaitConfirmation } from '@/lib/ui/AwaitableDialog.tsx';
import { GetCategoriesBaseQuery, GetCategoriesBaseQueryVariables } from '@/lib/graphql/generated/graphql.ts';
import { GetCategoriesBaseQuery, GetCategoriesBaseQueryVariables, MangaType } from '@/lib/graphql/generated/graphql.ts';
import { GET_CATEGORIES_BASE } from '@/lib/graphql/queries/CategoryQuery.ts';
export const useManageMangaLibraryState = (
manga: Pick<TManga, 'id' | 'title' | 'inLibrary'>,
manga: Pick<MangaType, 'id' | 'title'> & Partial<Pick<MangaType, 'inLibrary'>>,
confirmRemoval: boolean = false,
) => {
const { t } = useTranslation();
const navigate = useNavigate();
const [isInLibrary, setIsInLibrary] = useState(manga.inLibrary);
const [isInLibrary, setIsInLibrary] = useState(!!manga.inLibrary);
const addToLibrary = useCallback(
(didSubmit: boolean, addToCategories: number[] = [], removeFromCategories: number[] = []) => {
@@ -162,6 +161,6 @@ export const useManageMangaLibraryState = (
*
* To work around this issue, the currently known in library state gets returned here
*/
isInLibrary: Mangas.getFromCache<TManga>(manga.id)?.inLibrary ?? isInLibrary,
isInLibrary: Mangas.getFromCache(manga.id)?.inLibrary ?? isInLibrary,
};
};