Feature/download ahead while reading (#464)
* Download next chapters when marking chapter as read while reading * Add "auto delete chapter" settings * Delete chapter after finished reading * Delete chapters after marking them as read * Improve "mark previous as read" action Send only ids of chapters that are actually unread
This commit is contained in:
@@ -32,10 +32,11 @@ import { getUploadDateString } from '@/util/date';
|
||||
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
||||
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { TChapter } from '@/typings.ts';
|
||||
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
|
||||
|
||||
interface IProps {
|
||||
chapter: TChapter;
|
||||
chapterIds: number[];
|
||||
allChapters: TChapter[];
|
||||
downloadChapter: DownloadType | undefined;
|
||||
showChapterNumber: boolean;
|
||||
onSelect: (selected: boolean) => void;
|
||||
@@ -46,9 +47,11 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
||||
const { chapter, chapterIds, downloadChapter: dc, showChapterNumber, onSelect, selected } = props;
|
||||
const { chapter, allChapters, downloadChapter: dc, showChapterNumber, onSelect, selected } = props;
|
||||
const isSelecting = selected !== null;
|
||||
|
||||
const { settings: metadataServerSettings } = useMetadataServerSettings();
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
|
||||
const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
@@ -67,9 +70,29 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||
const sendChange = <Key extends keyof UpdatePatchInput>(key: Key, value: UpdatePatchInput[Key]) => {
|
||||
handleClose();
|
||||
|
||||
const isMarkAsRead = (key === 'isRead' && value) || key === 'markPrevRead';
|
||||
const shouldAutoDeleteChapters = isMarkAsRead && metadataServerSettings.deleteChaptersManuallyMarkedRead;
|
||||
if (shouldAutoDeleteChapters) {
|
||||
const shouldDeleteChapter = ({ isBookmarked, isDownloaded }: TChapter) =>
|
||||
isDownloaded && (!isBookmarked || metadataServerSettings.deleteChaptersWithBookmark);
|
||||
|
||||
const chaptersToDelete = key === 'isRead' ? [chapter] : allChapters;
|
||||
const chapterIdsToDelete = chaptersToDelete
|
||||
.filter(shouldDeleteChapter)
|
||||
.map(({ id: chapterId }) => chapterId);
|
||||
|
||||
requestManager.deleteDownloadedChapters(chapterIdsToDelete).response.catch(() => {});
|
||||
}
|
||||
|
||||
if (key === 'markPrevRead') {
|
||||
const index = chapterIds.findIndex((chapterId) => chapterId === chapter.id);
|
||||
requestManager.updateChapters(chapterIds.slice(index), { isRead: true });
|
||||
const index = allChapters.findIndex(({ id: chapterId }) => chapterId === chapter.id);
|
||||
requestManager.updateChapters(
|
||||
allChapters
|
||||
.slice(index)
|
||||
.filter(({ isRead }) => !isRead)
|
||||
.map(({ id: chapterId }) => chapterId),
|
||||
{ isRead: true },
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { ChaptersToolbarMenu } from '@/components/manga/ChaptersToolbarMenu';
|
||||
import { SelectionFAB } from '@/components/manga/SelectionFAB';
|
||||
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
|
||||
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
|
||||
|
||||
const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({
|
||||
listStyle: 'none',
|
||||
@@ -89,7 +90,8 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
||||
const [options, dispatch] = useChapterOptions(manga.id);
|
||||
const { data: chaptersData, loading: isLoading, refetch } = requestManager.useGetMangaChapters(manga.id);
|
||||
const chapters = useMemo(() => chaptersData?.chapters.nodes ?? [], [chaptersData?.chapters.nodes]);
|
||||
const mangaChapterIds = useMemo(() => chapters.map((chapter) => chapter.id), [chapters]);
|
||||
|
||||
const { settings: metadataServerSettings } = useMetadataServerSettings();
|
||||
|
||||
useEffect(() => {
|
||||
if (prevQueueRef.current && queue) {
|
||||
@@ -164,6 +166,20 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
||||
} else {
|
||||
actionPromise = requestManager.updateChapters(chapterIds, change).response;
|
||||
}
|
||||
|
||||
const shouldDeleteChapters =
|
||||
action === 'mark_as_read' && metadataServerSettings.deleteChaptersManuallyMarkedRead;
|
||||
if (shouldDeleteChapters) {
|
||||
const chapterIdsToDelete = actionChapters
|
||||
.filter(
|
||||
({ chapter }) =>
|
||||
chapter.isDownloaded &&
|
||||
(!chapter.isBookmarked || metadataServerSettings.deleteChaptersWithBookmark),
|
||||
)
|
||||
.map(({ chapter }) => chapter.id);
|
||||
|
||||
requestManager.deleteDownloadedChapters(chapterIdsToDelete).response.catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
actionPromise
|
||||
@@ -285,7 +301,7 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
||||
return (
|
||||
<ChapterCard
|
||||
{...chaptersWithMeta[index]}
|
||||
chapterIds={mangaChapterIds}
|
||||
allChapters={chapters}
|
||||
showChapterNumber={options.showChapterNumber}
|
||||
onSelect={() => handleSelection(index)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user