Fix download queue related TypeErrors
With the changes from df006bb348, the requested download queue data changed not matching the previously used type.
The unnecessary cast then hid the tsc issues during compilation
This commit is contained in:
@@ -24,13 +24,14 @@ import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
|
|||||||
import { useLongPress } from 'use-long-press';
|
import { useLongPress } from 'use-long-press';
|
||||||
import { getDateString } from '@/util/date.ts';
|
import { getDateString } from '@/util/date.ts';
|
||||||
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator.tsx';
|
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator.tsx';
|
||||||
import { ChapterType, DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
import { ChapterType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
|
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
|
||||||
import { Menu } from '@/components/menu/Menu.tsx';
|
import { Menu } from '@/components/menu/Menu.tsx';
|
||||||
import { TypographyMaxLines } from '@/components/atoms/TypographyMaxLines.tsx';
|
import { TypographyMaxLines } from '@/components/atoms/TypographyMaxLines.tsx';
|
||||||
import {
|
import {
|
||||||
ChapterBookmarkInfo,
|
ChapterBookmarkInfo,
|
||||||
ChapterDownloadInfo,
|
ChapterDownloadInfo,
|
||||||
|
ChapterDownloadStatus,
|
||||||
ChapterIdInfo,
|
ChapterIdInfo,
|
||||||
ChapterMangaInfo,
|
ChapterMangaInfo,
|
||||||
ChapterNumberInfo,
|
ChapterNumberInfo,
|
||||||
@@ -50,7 +51,7 @@ type TChapter = ChapterIdInfo &
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
chapter: TChapter;
|
chapter: TChapter;
|
||||||
allChapters: TChapter[];
|
allChapters: TChapter[];
|
||||||
downloadChapter: DownloadType | undefined;
|
downloadChapter: ChapterDownloadStatus | undefined;
|
||||||
showChapterNumber: boolean;
|
showChapterNumber: boolean;
|
||||||
onSelect: (selected: boolean, isShiftKey?: boolean) => void;
|
onSelect: (selected: boolean, isShiftKey?: boolean) => void;
|
||||||
selected: boolean | null;
|
selected: boolean | null;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Stack from '@mui/material/Stack';
|
|||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React, { useMemo } from 'react';
|
import { ComponentProps, useMemo } from 'react';
|
||||||
import { Virtuoso } from 'react-virtuoso';
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
@@ -28,7 +28,6 @@ import { ChaptersToolbarMenu } from '@/components/chapter/ChaptersToolbarMenu.ts
|
|||||||
import { SelectionFAB } from '@/components/collection/SelectionFAB.tsx';
|
import { SelectionFAB } from '@/components/collection/SelectionFAB.tsx';
|
||||||
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab.tsx';
|
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab.tsx';
|
||||||
import {
|
import {
|
||||||
DownloadType,
|
|
||||||
GetChaptersMangaQuery,
|
GetChaptersMangaQuery,
|
||||||
GetChaptersMangaQueryVariables,
|
GetChaptersMangaQueryVariables,
|
||||||
MangaScreenFieldsFragment,
|
MangaScreenFieldsFragment,
|
||||||
@@ -36,7 +35,7 @@ import {
|
|||||||
import { useSelectableCollection } from '@/components/collection/useSelectableCollection.ts';
|
import { useSelectableCollection } from '@/components/collection/useSelectableCollection.ts';
|
||||||
import { SelectableCollectionSelectAll } from '@/components/collection/SelectableCollectionSelectAll.tsx';
|
import { SelectableCollectionSelectAll } from '@/components/collection/SelectableCollectionSelectAll.tsx';
|
||||||
import { Chapters } from '@/lib/data/Chapters.ts';
|
import { Chapters } from '@/lib/data/Chapters.ts';
|
||||||
import { ChaptersWithMeta } from '@/lib/data/ChaptersWithMeta.ts';
|
import { ChaptersWithMeta, ChapterWithMetaType } from '@/lib/data/ChaptersWithMeta.ts';
|
||||||
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
|
import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx';
|
||||||
import { ChaptersDownloadActionMenuItems } from '@/components/chapter/ChaptersDownloadActionMenuItems.tsx';
|
import { ChaptersDownloadActionMenuItems } from '@/components/chapter/ChaptersDownloadActionMenuItems.tsx';
|
||||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||||
@@ -65,25 +64,24 @@ const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface IChapterWithMeta {
|
export interface IChapterWithMeta extends ChapterWithMetaType<ComponentProps<typeof ChapterCard>['chapter']> {
|
||||||
chapter: React.ComponentProps<typeof ChapterCard>['chapter'];
|
|
||||||
downloadChapter: DownloadType | undefined;
|
|
||||||
selected: boolean | null;
|
selected: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
export const ChapterList = ({
|
||||||
|
manga,
|
||||||
|
isRefreshing,
|
||||||
|
}: {
|
||||||
manga: Pick<
|
manga: Pick<
|
||||||
MangaScreenFieldsFragment,
|
MangaScreenFieldsFragment,
|
||||||
'id' | 'firstUnreadChapter' | 'chapters' | 'latestReadChapter' | 'unreadCount' | 'downloadCount'
|
'id' | 'firstUnreadChapter' | 'chapters' | 'latestReadChapter' | 'unreadCount' | 'downloadCount'
|
||||||
>;
|
>;
|
||||||
isRefreshing: boolean;
|
isRefreshing: boolean;
|
||||||
}
|
}) => {
|
||||||
|
|
||||||
export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { data: downloaderData } = requestManager.useGetDownloadStatus();
|
const { data: downloaderData } = requestManager.useGetDownloadStatus();
|
||||||
const queue = (downloaderData?.downloadStatus.queue as DownloadType[]) ?? [];
|
const queue = downloaderData?.downloadStatus.queue ?? [];
|
||||||
|
|
||||||
const [options, dispatch] = useChapterOptions(manga.id);
|
const [options, dispatch] = useChapterOptions(manga.id);
|
||||||
const {
|
const {
|
||||||
@@ -117,9 +115,7 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
|||||||
const chaptersWithMeta: IChapterWithMeta[] = useMemo(
|
const chaptersWithMeta: IChapterWithMeta[] = useMemo(
|
||||||
() =>
|
() =>
|
||||||
visibleChapters.map((chapter) => {
|
visibleChapters.map((chapter) => {
|
||||||
const downloadChapter = queue?.find(
|
const downloadChapter = queue?.find((cd) => cd.chapter.id === chapter.id);
|
||||||
(cd) => cd.chapter.sourceOrder === chapter.sourceOrder && cd.chapter.manga.id === chapter.mangaId,
|
|
||||||
);
|
|
||||||
const selected = !areNoItemsSelected ? selectedItemIds.includes(chapter.id) : null;
|
const selected = !areNoItemsSelected ? selectedItemIds.includes(chapter.id) : null;
|
||||||
return {
|
return {
|
||||||
chapter,
|
chapter,
|
||||||
|
|||||||
@@ -9,14 +9,10 @@
|
|||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { TranslationKey } from '@/typings';
|
import { TranslationKey } from '@/typings';
|
||||||
import { DownloadState, DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
import { DownloadState } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
import { ChapterDownloadStatus } from '@/lib/data/Chapters.ts';
|
||||||
interface DownloadStateIndicatorProps {
|
|
||||||
download: DownloadType;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in DownloadState]: TranslationKey } = {
|
const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in DownloadState]: TranslationKey } = {
|
||||||
DOWNLOADING: 'download.state.label.downloading',
|
DOWNLOADING: 'download.state.label.downloading',
|
||||||
@@ -25,7 +21,7 @@ const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in DownloadState]: Transla
|
|||||||
QUEUED: 'download.state.label.queued',
|
QUEUED: 'download.state.label.queued',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const DownloadStateIndicator: React.FC<DownloadStateIndicatorProps> = ({ download }) => {
|
export const DownloadStateIndicator = ({ download }: { download: ChapterDownloadStatus }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ import { ChapterOffset, TranslationKey } from '@/typings.ts';
|
|||||||
import { makeToast } from '@/components/util/Toast.tsx';
|
import { makeToast } from '@/components/util/Toast.tsx';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { getMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
|
import { getMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
|
||||||
import { ChapterListFieldsFragment, ChapterType } from '@/lib/graphql/generated/graphql.ts';
|
import {
|
||||||
|
ChapterListFieldsFragment,
|
||||||
|
ChapterType,
|
||||||
|
DownloadStatusFieldsFragment,
|
||||||
|
} from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { CHAPTER_LIST_FIELDS } from '@/lib/graphql/fragments/ChapterFragments.ts';
|
import { CHAPTER_LIST_FIELDS } from '@/lib/graphql/fragments/ChapterFragments.ts';
|
||||||
import { MangaIdInfo } from '@/lib/data/Mangas.ts';
|
import { MangaIdInfo } from '@/lib/data/Mangas.ts';
|
||||||
|
|
||||||
@@ -79,6 +83,8 @@ export const actionToTranslationKey: {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ChapterDownloadStatus = DownloadStatusFieldsFragment['queue'][number];
|
||||||
|
|
||||||
export type ChapterIdInfo = Pick<ChapterType, 'id'>;
|
export type ChapterIdInfo = Pick<ChapterType, 'id'>;
|
||||||
export type ChapterMangaInfo = Pick<ChapterType, 'mangaId'>;
|
export type ChapterMangaInfo = Pick<ChapterType, 'mangaId'>;
|
||||||
export type ChapterDownloadInfo = ChapterIdInfo & Pick<ChapterType, 'isDownloaded'>;
|
export type ChapterDownloadInfo = ChapterIdInfo & Pick<ChapterType, 'isDownloaded'>;
|
||||||
|
|||||||
@@ -6,12 +6,21 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
import {
|
||||||
import { ChapterBookmarkInfo, ChapterDownloadInfo, ChapterReadInfo, Chapters } from '@/lib/data/Chapters.ts';
|
ChapterBookmarkInfo,
|
||||||
|
ChapterDownloadInfo,
|
||||||
|
ChapterDownloadStatus,
|
||||||
|
ChapterReadInfo,
|
||||||
|
Chapters,
|
||||||
|
} from '@/lib/data/Chapters.ts';
|
||||||
|
|
||||||
export type ChapterWithMetaType = {
|
export type ChapterWithMetaType<
|
||||||
chapter: ChapterDownloadInfo & ChapterReadInfo & ChapterBookmarkInfo;
|
Chapter extends ChapterDownloadInfo & ChapterReadInfo & ChapterBookmarkInfo = ChapterDownloadInfo &
|
||||||
downloadChapter: DownloadType | undefined;
|
ChapterReadInfo &
|
||||||
|
ChapterBookmarkInfo,
|
||||||
|
> = {
|
||||||
|
chapter: Chapter;
|
||||||
|
downloadChapter: ChapterDownloadStatus | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ChaptersWithMeta {
|
export class ChaptersWithMeta {
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ import { StrictModeDroppable } from '@/lib/StrictModeDroppable';
|
|||||||
import { makeToast } from '@/components/util/Toast';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
||||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||||
import { ChapterType, DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
|
||||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder.tsx';
|
||||||
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
|
||||||
import { ChapterIdInfo } from '@/lib/data/Chapters.ts';
|
import { ChapterDownloadStatus, ChapterIdInfo } from '@/lib/data/Chapters.ts';
|
||||||
|
|
||||||
const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
|
const HeightPreservingItem = ({ children, ...props }: BoxProps) => (
|
||||||
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
|
// the height is necessary to prevent the item container from collapsing, which confuses Virtuoso measurements
|
||||||
@@ -48,9 +47,9 @@ const DownloadChapterItem = ({
|
|||||||
handleDelete,
|
handleDelete,
|
||||||
}: {
|
}: {
|
||||||
provided: DraggableProvided;
|
provided: DraggableProvided;
|
||||||
item: DownloadType;
|
item: ChapterDownloadStatus;
|
||||||
isDragging: boolean;
|
isDragging: boolean;
|
||||||
handleDelete: (chapter: ChapterType) => void;
|
handleDelete: (chapter: ChapterIdInfo) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -63,7 +62,7 @@ const DownloadChapterItem = ({
|
|||||||
>
|
>
|
||||||
<CardActionArea
|
<CardActionArea
|
||||||
component={Link}
|
component={Link}
|
||||||
to={`/manga/${item.chapter.manga.id}`}
|
to={`/manga/${item.manga.id}`}
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -74,7 +73,7 @@ const DownloadChapterItem = ({
|
|||||||
<DragHandle />
|
<DragHandle />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Stack sx={{ flex: 1, ml: 1 }} direction="column">
|
<Stack sx={{ flex: 1, ml: 1 }} direction="column">
|
||||||
<Typography variant="h6">{item.chapter.manga.title}</Typography>
|
<Typography variant="h6">{item.manga.title}</Typography>
|
||||||
<Typography variant="caption" display="block" gutterBottom>
|
<Typography variant="caption" display="block" gutterBottom>
|
||||||
{item.chapter.name}
|
{item.chapter.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -111,7 +110,7 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
} = requestManager.useGetDownloadStatus({ notifyOnNetworkStatusChange: true });
|
} = requestManager.useGetDownloadStatus({ notifyOnNetworkStatusChange: true });
|
||||||
const downloaderData = downloadStatusData?.downloadStatus;
|
const downloaderData = downloadStatusData?.downloadStatus;
|
||||||
|
|
||||||
const queue = (downloaderData?.queue as DownloadType[]) ?? [];
|
const queue = downloaderData?.queue ?? [];
|
||||||
const status = downloaderData?.state ?? 'STARTED';
|
const status = downloaderData?.state ?? 'STARTED';
|
||||||
const isQueueEmpty = !queue.length;
|
const isQueueEmpty = !queue.length;
|
||||||
|
|
||||||
@@ -174,7 +173,7 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
return () => window.removeEventListener('error', ignoreError);
|
return () => window.removeEventListener('error', ignoreError);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const categoryReorder = (list: DownloadType[], from: number, to: number) => {
|
const categoryReorder = (list: ChapterDownloadStatus[], from: number, to: number) => {
|
||||||
if (from === to) {
|
if (from === to) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -262,8 +261,8 @@ export const DownloadQueue: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
itemContent={(index, item) => (
|
itemContent={(index, item) => (
|
||||||
<Draggable
|
<Draggable
|
||||||
key={`${item.chapter.manga.id}-${item.chapter.sourceOrder}`}
|
key={`${item.manga.id}-${item.chapter.sourceOrder}`}
|
||||||
draggableId={`${item.chapter.manga.id}-${item.chapter.sourceOrder}`}
|
draggableId={`${item.manga.id}-${item.chapter.sourceOrder}`}
|
||||||
index={index}
|
index={index}
|
||||||
>
|
>
|
||||||
{(draggableProvided) => (
|
{(draggableProvided) => (
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { requestManager } from '@/lib/requests/RequestManager.ts';
|
|||||||
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
||||||
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
import { EmptyViewAbsoluteCentered } from '@/components/util/EmptyViewAbsoluteCentered.tsx';
|
||||||
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
||||||
import { ChapterType, DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
import { ChapterType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
import { UpdateChecker } from '@/components/library/UpdateChecker.tsx';
|
import { UpdateChecker } from '@/components/library/UpdateChecker.tsx';
|
||||||
import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuoso.tsx';
|
import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuoso.tsx';
|
||||||
@@ -70,7 +70,7 @@ export const Updates: React.FC = () => {
|
|||||||
const groupedUpdates = useMemo(() => groupByDate(updateEntries), [updateEntries]);
|
const groupedUpdates = useMemo(() => groupByDate(updateEntries), [updateEntries]);
|
||||||
const groupCounts: number[] = useMemo(() => groupedUpdates.map((group) => group[1]), [groupedUpdates]);
|
const groupCounts: number[] = useMemo(() => groupedUpdates.map((group) => group[1]), [groupedUpdates]);
|
||||||
const { data: downloaderData } = requestManager.useGetDownloadStatus();
|
const { data: downloaderData } = requestManager.useGetDownloadStatus();
|
||||||
const queue = (downloaderData?.downloadStatus.queue as DownloadType[]) ?? [];
|
const queue = downloaderData?.downloadStatus.queue ?? [];
|
||||||
|
|
||||||
const lastUpdateTimestampCompRef = useRef<HTMLElement>(null);
|
const lastUpdateTimestampCompRef = useRef<HTMLElement>(null);
|
||||||
const [lastUpdateTimestampCompHeight, setLastUpdateTimestampCompHeight] = useState(0);
|
const [lastUpdateTimestampCompHeight, setLastUpdateTimestampCompHeight] = useState(0);
|
||||||
@@ -98,7 +98,7 @@ export const Updates: React.FC = () => {
|
|||||||
|
|
||||||
const downloadForChapter = (chapter: Pick<ChapterType, 'sourceOrder'> & ChapterMangaInfo) => {
|
const downloadForChapter = (chapter: Pick<ChapterType, 'sourceOrder'> & ChapterMangaInfo) => {
|
||||||
const { sourceOrder, mangaId } = chapter;
|
const { sourceOrder, mangaId } = chapter;
|
||||||
return queue.find((q) => sourceOrder === q.chapter.sourceOrder && mangaId === q.chapter.manga.id);
|
return queue.find((q) => sourceOrder === q.chapter.sourceOrder && mangaId === q.manga.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadChapter = (chapter: ChapterIdInfo) => {
|
const downloadChapter = (chapter: ChapterIdInfo) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user