[Codegen] Use gql for "loading chapters"
This commit is contained in:
@@ -27,16 +27,15 @@ import Typography from '@mui/material/Typography';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IChapter, IDownloadChapter } from '@/typings';
|
||||
import { IDownloadChapter } from '@/typings';
|
||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||
import { getUploadDateString } from '@/util/date';
|
||||
import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator';
|
||||
import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { ChapterType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
interface IProps {
|
||||
chapter: IChapter;
|
||||
chapter: ChapterType;
|
||||
chapterIds: number[];
|
||||
triggerChaptersUpdate: () => void;
|
||||
downloadChapter: IDownloadChapter | undefined;
|
||||
showChapterNumber: boolean;
|
||||
onSelect: (selected: boolean) => void;
|
||||
@@ -47,15 +46,7 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
||||
const {
|
||||
chapter,
|
||||
chapterIds,
|
||||
triggerChaptersUpdate,
|
||||
downloadChapter: dc,
|
||||
showChapterNumber,
|
||||
onSelect,
|
||||
selected,
|
||||
} = props;
|
||||
const { chapter, chapterIds, downloadChapter: dc, showChapterNumber, onSelect, selected } = props;
|
||||
const isSelecting = selected !== null;
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
@@ -82,12 +73,10 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
requestManager
|
||||
.updateChapter(chapter.id, {
|
||||
[key]: value,
|
||||
lastPageRead: key === 'isRead' ? 0 : undefined,
|
||||
})
|
||||
.response.then(() => triggerChaptersUpdate());
|
||||
requestManager.updateChapter(chapter.id, {
|
||||
[key]: value,
|
||||
lastPageRead: key === 'isRead' ? 0 : undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const downloadChapter = () => {
|
||||
@@ -96,7 +85,7 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
};
|
||||
|
||||
const deleteChapter = () => {
|
||||
requestManager.deleteDownloadedChapter(chapter.id).response.then(() => triggerChaptersUpdate());
|
||||
requestManager.deleteDownloadedChapter(chapter.id);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
@@ -113,8 +102,8 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
const isDownloaded = chapter.downloaded;
|
||||
const canBeDownloaded = !chapter.downloaded && dc === undefined;
|
||||
const { isDownloaded } = chapter;
|
||||
const canBeDownloaded = !chapter.isDownloaded && dc === undefined;
|
||||
|
||||
return (
|
||||
<li>
|
||||
@@ -126,9 +115,9 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
>
|
||||
<CardActionArea
|
||||
component={Link}
|
||||
to={`/manga/${chapter.mangaId}/chapter/${chapter.index}`}
|
||||
to={`/manga/${chapter.manga.id}/chapter/${chapter.sourceOrder}`}
|
||||
style={{
|
||||
color: theme.palette.text[chapter.read ? 'disabled' : 'primary'],
|
||||
color: theme.palette.text[chapter.isRead ? 'disabled' : 'primary'],
|
||||
}}
|
||||
onClick={handleClick}
|
||||
>
|
||||
@@ -143,7 +132,7 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
>
|
||||
<Stack direction="column" flex={1}>
|
||||
<Typography variant="h5" component="h2">
|
||||
{chapter.bookmarked && (
|
||||
{chapter.isBookmarked && (
|
||||
<BookmarkIcon
|
||||
color="primary"
|
||||
sx={{ mr: 0.5, position: 'relative', top: '0.15em' }}
|
||||
@@ -153,7 +142,7 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
</Typography>
|
||||
<Typography variant="caption">{chapter.scanlator}</Typography>
|
||||
<Typography variant="caption">
|
||||
{getUploadDateString(chapter.uploadDate)}
|
||||
{getUploadDateString(Number(chapter.uploadDate ?? 0))}
|
||||
{isDownloaded && ` • ${t('chapter.status.label.downloaded')}`}
|
||||
</Typography>
|
||||
</Stack>
|
||||
@@ -192,24 +181,24 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
<ListItemText>{t('chapter.action.download.add.label.action')}</ListItemText>
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={() => sendChange('isBookmarked', !chapter.bookmarked)}>
|
||||
<MenuItem onClick={() => sendChange('isBookmarked', !chapter.isBookmarked)}>
|
||||
<ListItemIcon>
|
||||
{chapter.bookmarked && <BookmarkRemove fontSize="small" />}
|
||||
{!chapter.bookmarked && <BookmarkAdd fontSize="small" />}
|
||||
{chapter.isBookmarked && <BookmarkRemove fontSize="small" />}
|
||||
{!chapter.isBookmarked && <BookmarkAdd fontSize="small" />}
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
{chapter.bookmarked && t('chapter.action.bookmark.remove.label.action')}
|
||||
{!chapter.bookmarked && t('chapter.action.bookmark.add.label.action')}
|
||||
{chapter.isBookmarked && t('chapter.action.bookmark.remove.label.action')}
|
||||
{!chapter.isBookmarked && t('chapter.action.bookmark.add.label.action')}
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => sendChange('isRead', !chapter.read)}>
|
||||
<MenuItem onClick={() => sendChange('isRead', !chapter.isRead)}>
|
||||
<ListItemIcon>
|
||||
{chapter.read && <RemoveDone fontSize="small" />}
|
||||
{!chapter.read && <Done fontSize="small" />}
|
||||
{chapter.isRead && <RemoveDone fontSize="small" />}
|
||||
{!chapter.isRead && <Done fontSize="small" />}
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
{chapter.read && t('chapter.action.mark_as_read.remove.label.action')}
|
||||
{!chapter.read && t('chapter.action.mark_as_read.add.label.action.current')}
|
||||
{chapter.isRead && t('chapter.action.mark_as_read.remove.label.action')}
|
||||
{!chapter.isRead && t('chapter.action.mark_as_read.add.label.action.current')}
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => sendChange('markPrevRead', true)}>
|
||||
|
||||
@@ -11,7 +11,7 @@ import Typography from '@mui/material/Typography';
|
||||
import React, { ComponentProps, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IChapter, IDownloadChapter, IQueue, TranslationKey } from '@/typings';
|
||||
import { IDownloadChapter, IQueue, TranslationKey } from '@/typings';
|
||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||
import useSubscription from '@/components/library/useSubscription';
|
||||
import ChapterCard from '@/components/manga/ChapterCard';
|
||||
@@ -22,7 +22,7 @@ import makeToast from '@/components/util/Toast';
|
||||
import ChaptersToolbarMenu from '@/components/manga/ChaptersToolbarMenu';
|
||||
import SelectionFAB from '@/components/manga/SelectionFAB';
|
||||
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
|
||||
import { UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { ChapterType, MangaType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({
|
||||
listStyle: 'none',
|
||||
@@ -69,25 +69,29 @@ const actionsStrings: {
|
||||
};
|
||||
|
||||
export interface IChapterWithMeta {
|
||||
chapter: IChapter;
|
||||
chapter: ChapterType;
|
||||
downloadChapter: IDownloadChapter | undefined;
|
||||
selected: boolean | null;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
mangaId: string;
|
||||
manga: MangaType;
|
||||
isRefreshing: boolean;
|
||||
}
|
||||
|
||||
const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [selection, setSelection] = useState<number[] | null>(null);
|
||||
const prevQueueRef = useRef<IDownloadChapter[]>();
|
||||
const queue = useSubscription<IQueue>('downloads').data?.queue;
|
||||
|
||||
const [options, dispatch] = useChapterOptions(mangaId);
|
||||
const { data: chaptersData, mutate, isLoading } = requestManager.useGetMangaChapters(mangaId);
|
||||
const chapters = useMemo(() => chaptersData ?? [], [chaptersData]);
|
||||
const [options, dispatch] = useChapterOptions(manga.id);
|
||||
const { data: chaptersData, loading: isLoading, refetch } = requestManager.useGetMangaChapters(manga.id);
|
||||
const chapters = useMemo(
|
||||
() => (chaptersData?.chapters.nodes as ChapterType[]) ?? [],
|
||||
[chaptersData?.chapters.nodes],
|
||||
);
|
||||
const mangaChapterIds = useMemo(() => chapters.map((chapter) => chapter.id), [chapters]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -102,26 +106,17 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
});
|
||||
|
||||
if (changedDownloads.length > 0) {
|
||||
mutate();
|
||||
refetch();
|
||||
}
|
||||
}
|
||||
|
||||
prevQueueRef.current = queue;
|
||||
}, [queue]);
|
||||
|
||||
const visibleChapters = useMemo(
|
||||
() => filterAndSortChapters(chapters, options), //
|
||||
[chapters, options],
|
||||
);
|
||||
const visibleChapters = useMemo(() => filterAndSortChapters(chapters, options), [chapters, options]);
|
||||
|
||||
const firstUnreadChapter = useMemo(
|
||||
() =>
|
||||
chapters
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((chapter) => !chapter.read),
|
||||
[chapters],
|
||||
);
|
||||
const nextChapterIndexToRead = (manga.lastReadChapter?.sourceOrder ?? 0) + 1;
|
||||
const isLatestChapterRead = manga.chapters.totalCount === manga.lastReadChapter?.sourceOrder;
|
||||
|
||||
const handleSelection = (index: number) => {
|
||||
const chapter = visibleChapters[index];
|
||||
@@ -174,11 +169,49 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
|
||||
actionPromise
|
||||
.then(() => makeToast(t(actionsStrings[action].success, { count: chapterIds.length }), 'success'))
|
||||
.then(() => mutate())
|
||||
.catch(() => makeToast(t(actionsStrings[action].error, { count: chapterIds.length }), 'error'));
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
const noChaptersFound = chapters.length === 0;
|
||||
const noChaptersMatchingFilter = !noChaptersFound && visibleChapters.length === 0;
|
||||
|
||||
const chaptersWithMeta: IChapterWithMeta[] = useMemo(
|
||||
() =>
|
||||
visibleChapters.map((chapter) => {
|
||||
const downloadChapter = queue?.find(
|
||||
(cd) => cd.chapterIndex === chapter.sourceOrder && cd.mangaId === chapter.manga.id,
|
||||
);
|
||||
const selected = selection?.includes(chapter.id) ?? null;
|
||||
return {
|
||||
chapter,
|
||||
downloadChapter,
|
||||
selected,
|
||||
};
|
||||
}),
|
||||
[queue, selection, visibleChapters],
|
||||
);
|
||||
|
||||
const selectedChapters = useMemo(() => {
|
||||
if (!selection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return chaptersWithMeta.filter(({ chapter }) => selection.includes(chapter.id));
|
||||
}, [selection, chapters]);
|
||||
|
||||
const chapterListFAB = useMemo(() => {
|
||||
if (selectedChapters) {
|
||||
return <SelectionFAB selectedChapters={selectedChapters} onAction={handleFabAction} />;
|
||||
}
|
||||
|
||||
if (!isLatestChapterRead) {
|
||||
return <ResumeFab chapterIndex={nextChapterIndexToRead} mangaId={manga.id} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [selectedChapters, isLatestChapterRead]);
|
||||
|
||||
if (isLoading || (noChaptersFound && isRefreshing)) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -192,24 +225,6 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const noChaptersFound = chapters.length === 0;
|
||||
const noChaptersMatchingFilter = !noChaptersFound && visibleChapters.length === 0;
|
||||
|
||||
const chaptersWithMeta: IChapterWithMeta[] = visibleChapters.map((chapter) => {
|
||||
const downloadChapter = queue?.find(
|
||||
(cd) => cd.chapterIndex === chapter.index && cd.mangaId === chapter.mangaId,
|
||||
);
|
||||
const selected = selection?.includes(chapter.id) ?? null;
|
||||
return {
|
||||
chapter,
|
||||
downloadChapter,
|
||||
selected,
|
||||
};
|
||||
});
|
||||
|
||||
const selectedChapters =
|
||||
selection === null ? null : chaptersWithMeta.filter(({ chapter }) => selection.includes(chapter.id));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack direction="column" sx={{ position: 'relative' }}>
|
||||
@@ -273,7 +288,6 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
{...chaptersWithMeta[index]}
|
||||
chapterIds={mangaChapterIds}
|
||||
showChapterNumber={options.showChapterNumber}
|
||||
triggerChaptersUpdate={() => mutate()}
|
||||
onSelect={() => handleSelection(index)}
|
||||
/>
|
||||
);
|
||||
@@ -282,11 +296,7 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
||||
overscan={window.innerHeight * 0.5}
|
||||
/>
|
||||
</Stack>
|
||||
{selectedChapters !== null ? (
|
||||
<SelectionFAB selectedChapters={selectedChapters} onAction={handleFabAction} />
|
||||
) : (
|
||||
firstUnreadChapter && <ResumeFab chapter={firstUnreadChapter} mangaId={mangaId} />
|
||||
)}
|
||||
{chapterListFAB}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,25 +9,21 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { PlayArrow } from '@mui/icons-material';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IChapter } from '@/typings';
|
||||
import StyledFab from '@/components/util/StyledFab';
|
||||
|
||||
interface ResumeFABProps {
|
||||
chapter: IChapter;
|
||||
mangaId: string;
|
||||
chapterIndex: number;
|
||||
mangaId: number;
|
||||
}
|
||||
|
||||
export default function ResumeFab(props: ResumeFABProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const {
|
||||
chapter: { index },
|
||||
mangaId,
|
||||
} = props;
|
||||
const { chapterIndex, mangaId } = props;
|
||||
return (
|
||||
<StyledFab component={Link} variant="extended" color="primary" to={`/manga/${mangaId}/chapter/${index}`}>
|
||||
<StyledFab component={Link} variant="extended" color="primary" to={`/manga/${mangaId}/chapter/${chapterIndex}`}>
|
||||
<PlayArrow />
|
||||
{index === 1 ? t('global.button.start') : t('global.button.resume')}
|
||||
{chapterIndex === 1 ? t('global.button.start') : t('global.button.resume')}
|
||||
</StyledFab>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,38 +63,38 @@ const SelectionFAB: React.FC<SelectionFABProps> = (props) => {
|
||||
<SelectionFABActionItem
|
||||
action="download"
|
||||
matchingChapters={selectedChapters.filter(
|
||||
({ chapter: c, downloadChapter: dc }) => !c.downloaded && dc === undefined,
|
||||
({ chapter: c, downloadChapter: dc }) => !c.isDownloaded && dc === undefined,
|
||||
)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.download.add.button.selected')}
|
||||
/>
|
||||
<SelectionFABActionItem
|
||||
action="delete"
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.downloaded)}
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isDownloaded)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.download.delete.button.selected')}
|
||||
/>
|
||||
<SelectionFABActionItem
|
||||
action="bookmark"
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.bookmarked)}
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.isBookmarked)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.bookmark.add.button.selected')}
|
||||
/>
|
||||
<SelectionFABActionItem
|
||||
action="unbookmark"
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.bookmarked)}
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isBookmarked)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.bookmark.remove.button.selected')}
|
||||
/>
|
||||
<SelectionFABActionItem
|
||||
action="mark_as_read"
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.read)}
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => !chapter.isRead)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.mark_as_read.add.button.selected')}
|
||||
/>
|
||||
<SelectionFABActionItem
|
||||
action="mark_as_unread"
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.read)}
|
||||
matchingChapters={selectedChapters.filter(({ chapter }) => chapter.isRead)}
|
||||
onClick={handleAction}
|
||||
title={t('chapter.action.mark_as_read.remove.button.selected')}
|
||||
/>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { mutate } from 'swr';
|
||||
import requestManager, { RequestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||
|
||||
export const useRefreshManga = (mangaId: string) => {
|
||||
const [fetchingOnline, setFetchingOnline] = useState(false);
|
||||
@@ -16,14 +15,8 @@ export const useRefreshManga = (mangaId: string) => {
|
||||
const handleRefresh = useCallback(async () => {
|
||||
setFetchingOnline(true);
|
||||
await Promise.all([
|
||||
requestManager.getMangaFetch(mangaId).response.then((res) => {
|
||||
mutate(`${RequestManager.API_VERSION}manga/${mangaId}`, res, { revalidate: false });
|
||||
}),
|
||||
requestManager.getMangaChapters(mangaId, true).response.then((res) =>
|
||||
mutate(`${RequestManager.API_VERSION}manga/${mangaId}/chapters`, res, {
|
||||
revalidate: false,
|
||||
}),
|
||||
),
|
||||
requestManager.getMangaFetch(mangaId, { awaitRefetchQueries: true }).response,
|
||||
requestManager.getMangaChaptersFetch(mangaId, { awaitRefetchQueries: true }).response,
|
||||
]).finally(() => setFetchingOnline(false));
|
||||
}, [mangaId]);
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
ChapterListOptions,
|
||||
ChapterOptionsReducerAction,
|
||||
ChapterSortMode,
|
||||
IChapter,
|
||||
NullAndUndefined,
|
||||
TranslationKey,
|
||||
} from '@/typings';
|
||||
import { useReducerLocalStorage } from '@/util/useLocalStorage';
|
||||
import { ChapterType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const defaultChapterOptions: ChapterListOptions = {
|
||||
active: false,
|
||||
@@ -46,7 +46,7 @@ function chapterOptionsReducer(state: ChapterListOptions, actions: ChapterOption
|
||||
}
|
||||
}
|
||||
|
||||
export function unreadFilter(unread: NullAndUndefined<boolean>, { read: isChapterRead }: IChapter) {
|
||||
export function unreadFilter(unread: NullAndUndefined<boolean>, { isRead: isChapterRead }: ChapterType) {
|
||||
switch (unread) {
|
||||
case true:
|
||||
return !isChapterRead;
|
||||
@@ -57,7 +57,7 @@ export function unreadFilter(unread: NullAndUndefined<boolean>, { read: isChapte
|
||||
}
|
||||
}
|
||||
|
||||
function downloadFilter(downloaded: NullAndUndefined<boolean>, { downloaded: chapterDownload }: IChapter) {
|
||||
function downloadFilter(downloaded: NullAndUndefined<boolean>, { isDownloaded: chapterDownload }: ChapterType) {
|
||||
switch (downloaded) {
|
||||
case true:
|
||||
return chapterDownload;
|
||||
@@ -68,7 +68,7 @@ function downloadFilter(downloaded: NullAndUndefined<boolean>, { downloaded: cha
|
||||
}
|
||||
}
|
||||
|
||||
function bookmarkedFilter(bookmarked: NullAndUndefined<boolean>, { bookmarked: chapterBookmarked }: IChapter) {
|
||||
function bookmarkedFilter(bookmarked: NullAndUndefined<boolean>, { isBookmarked: chapterBookmarked }: ChapterType) {
|
||||
switch (bookmarked) {
|
||||
case true:
|
||||
return chapterBookmarked;
|
||||
@@ -79,7 +79,7 @@ function bookmarkedFilter(bookmarked: NullAndUndefined<boolean>, { bookmarked: c
|
||||
}
|
||||
}
|
||||
|
||||
export function filterAndSortChapters(chapters: IChapter[], options: ChapterListOptions): IChapter[] {
|
||||
export function filterAndSortChapters(chapters: ChapterType[], options: ChapterListOptions): ChapterType[] {
|
||||
const filtered = options.active
|
||||
? chapters.filter(
|
||||
(chp) =>
|
||||
@@ -88,14 +88,17 @@ export function filterAndSortChapters(chapters: IChapter[], options: ChapterList
|
||||
bookmarkedFilter(options.bookmarked, chp),
|
||||
)
|
||||
: [...chapters];
|
||||
const Sorted = options.sortBy === 'fetchedAt' ? filtered.sort((a, b) => a.fetchedAt - b.fetchedAt) : filtered;
|
||||
const Sorted =
|
||||
options.sortBy === 'fetchedAt'
|
||||
? filtered.sort((a, b) => Number(a.fetchedAt ?? 0) - Number(b.fetchedAt ?? 0))
|
||||
: filtered;
|
||||
if (options.reverse) {
|
||||
Sorted.reverse();
|
||||
}
|
||||
return Sorted;
|
||||
}
|
||||
|
||||
export const useChapterOptions = (mangaId: string) =>
|
||||
export const useChapterOptions = (mangaId: number) =>
|
||||
useReducerLocalStorage<ChapterListOptions, ChapterOptionsReducerAction>(
|
||||
chapterOptionsReducer,
|
||||
`${mangaId}filterOptions`,
|
||||
|
||||
@@ -24,9 +24,9 @@ import ListItemText from '@mui/material/ListItemText';
|
||||
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
||||
import Collapse from '@mui/material/Collapse';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ChapterOffset, IChapter, IReaderSettings } from '@/typings';
|
||||
import { ChapterOffset, IReaderSettings } from '@/typings';
|
||||
import ReaderSettingsOptions from '@/components/reader/ReaderSettingsOptions';
|
||||
import { MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { ChapterType, MangaType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const Root = styled('div')(({ theme }) => ({
|
||||
top: 0,
|
||||
@@ -115,8 +115,8 @@ const OpenDrawerButton = styled(IconButton)(({ theme }) => ({
|
||||
interface IProps {
|
||||
settings: IReaderSettings;
|
||||
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
||||
manga: Pick<MangaType, 'id'>;
|
||||
chapter: IChapter;
|
||||
manga: MangaType;
|
||||
chapter: ChapterType;
|
||||
curPage: number;
|
||||
scrollToPage: (page: number) => void;
|
||||
openNextChapter: (offset: ChapterOffset, setHistory: (nextChapterIndex: number) => void) => Promise<void>;
|
||||
@@ -304,7 +304,7 @@ export default function ReaderNavBar(props: IProps) {
|
||||
<IconButton
|
||||
title={t('reader.button.previous_chapter')}
|
||||
sx={{ gridArea: 'pre' }}
|
||||
disabled={disableChapterNavButtons || chapter.index <= 1}
|
||||
disabled={disableChapterNavButtons || chapter.sourceOrder <= 1}
|
||||
onClick={() =>
|
||||
openNextChapter(ChapterOffset.PREV, (prevChapterIndex) => {
|
||||
navigate(`/manga/${manga.id}/chapter/${prevChapterIndex}`, {
|
||||
@@ -322,11 +322,11 @@ export default function ReaderNavBar(props: IProps) {
|
||||
<FormControl
|
||||
sx={{ gridArea: 'current' }}
|
||||
size="small"
|
||||
disabled={disableChapterNavButtons || chapter.index < 1}
|
||||
disabled={disableChapterNavButtons || chapter.sourceOrder < 1}
|
||||
>
|
||||
<Select
|
||||
MenuProps={MenuProps}
|
||||
value={chapter.index >= 1 ? chapter.index : ''}
|
||||
value={chapter.sourceOrder >= 1 ? chapter.sourceOrder : ''}
|
||||
displayEmpty
|
||||
onChange={({ target: { value: selectedChapter } }) => {
|
||||
navigate(`/manga/${manga.id}/chapter/${selectedChapter}`, {
|
||||
@@ -338,7 +338,7 @@ export default function ReaderNavBar(props: IProps) {
|
||||
});
|
||||
}}
|
||||
>
|
||||
{Array(Math.max(0, chapter.chapterCount))
|
||||
{Array(Math.max(0, manga.chapters.totalCount))
|
||||
.fill(1)
|
||||
.map((ignoreValue, index) => (
|
||||
<MenuItem key={`Chapter#${index + 1}`} value={index + 1}>{`${t(
|
||||
@@ -352,8 +352,8 @@ export default function ReaderNavBar(props: IProps) {
|
||||
sx={{ gridArea: 'next' }}
|
||||
disabled={
|
||||
disableChapterNavButtons ||
|
||||
chapter.index < 1 ||
|
||||
chapter.index >= chapter.chapterCount
|
||||
chapter.sourceOrder < 1 ||
|
||||
chapter.sourceOrder >= manga.chapters.totalCount
|
||||
}
|
||||
onClick={() => {
|
||||
openNextChapter(ChapterOffset.NEXT, (nextChapterIndex) =>
|
||||
|
||||
Reference in New Issue
Block a user