From b4c1cdee77fa76eed88bd5377aad58060b61cdd6 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:45:11 +0100 Subject: [PATCH] Handle chapter updates sync in reader To be able to properly prevent unnecessary chapter updates, the ongoing updates have to finish, so that the apollo cache is update to date. Otherwise, the update guard will always be false since the apollo caches chapter data is still from before the previous updates were triggered. --- src/modules/reader/services/ReaderService.ts | 96 ++++++++++++-------- 1 file changed, 57 insertions(+), 39 deletions(-) diff --git a/src/modules/reader/services/ReaderService.ts b/src/modules/reader/services/ReaderService.ts index d4eb92bc..7ec6c12f 100644 --- a/src/modules/reader/services/ReaderService.ts +++ b/src/modules/reader/services/ReaderService.ts @@ -11,7 +11,7 @@ import { useNavigate } from 'react-router-dom'; import { Direction, useTheme } from '@mui/material/styles'; import { t as translate } from 'i18next'; import { TChapterReader } from '@/modules/chapter/Chapter.types.ts'; -import { Chapters } from '@/modules/chapter/services/Chapters.ts'; +import { ChapterIdInfo, Chapters } from '@/modules/chapter/services/Chapters.ts'; import { IReaderSettings, IReaderSettingsWithDefaultFlag, @@ -59,6 +59,16 @@ const DIRECTION_TO_READING_DIRECTION: Record = { export class ReaderService { private static downloadAheadQueue: Queue = new Queue(1); + private static chapterUpdateQueues: Map = new Map(); + + private static getOrCreateChapterUpdateQueue(id: ChapterIdInfo['id']): Queue { + if (!this.chapterUpdateQueues.has(id)) { + this.chapterUpdateQueues.set(id, new Queue(1)); + } + + return this.chapterUpdateQueues.get(id)!; + } + static useNavigateToChapter(chapter?: TChapterReader, resumeMode?: ReaderResumeMode): () => void { const navigate = useNavigate(); return useCallback( @@ -130,50 +140,58 @@ export class ReaderService { return; } - const chapterIdsToUpdate = Chapters.getIds( - shouldSkipDupChapters ? Chapters.addDuplicates([currentChapter], mangaChapters) : [currentChapter], - ); + const update = async () => { + const chapterIdsToUpdate = Chapters.getIds( + shouldSkipDupChapters + ? Chapters.addDuplicates([currentChapter], mangaChapters) + : [currentChapter], + ); - const isUpdateRequired = chapterIdsToUpdate.some((id) => { - const chapterUpToDateData = getReaderChapterFromCache(id); - if (!chapterUpToDateData) { - return false; + const isUpdateRequired = chapterIdsToUpdate.some((id) => { + const chapterUpToDateData = getReaderChapterFromCache(id); + if (!chapterUpToDateData) { + return false; + } + + return ( + (patch.isRead !== undefined && patch.isRead !== chapterUpToDateData.isRead) || + (patch.lastPageRead !== undefined && + patch.lastPageRead !== chapterUpToDateData.lastPageRead) || + (patch.isBookmarked !== undefined && + patch.isBookmarked !== chapterUpToDateData.isBookmarked) + ); + }); + if (!isUpdateRequired) { + return; } - return ( - (patch.isRead !== undefined && patch.isRead !== chapterUpToDateData.isRead) || - (patch.lastPageRead !== undefined && patch.lastPageRead !== chapterUpToDateData.lastPageRead) || - (patch.isBookmarked !== undefined && patch.isBookmarked !== chapterUpToDateData.isBookmarked) + const chapterIdsToDelete = getChapterIdsToDeleteForChapterUpdate( + currentChapter, + mangaChapters, + previousChapters, + patch, + deleteChaptersWhileReading, + deleteChaptersWithBookmark, + shouldSkipDupChapters, ); - }); - if (!isUpdateRequired) { - return; - } - const chapterIdsToDelete = getChapterIdsToDeleteForChapterUpdate( - currentChapter, - mangaChapters, - previousChapters, - patch, - deleteChaptersWhileReading, - deleteChaptersWithBookmark, - shouldSkipDupChapters, - ); + await requestManager + .updateChapters( + chapterIdsToUpdate, + { + ...patch, + chapterIdsToDelete, + trackProgressMangaId: + updateProgressAfterReading && patch.isRead && manga.trackRecords.totalCount + ? manga.id + : undefined, + }, + { errorPolicy: 'all' }, + ) + .response.catch(defaultPromiseErrorHandler('ReaderService::useUpdateChapter')); + }; - requestManager - .updateChapters( - chapterIdsToUpdate, - { - ...patch, - chapterIdsToDelete, - trackProgressMangaId: - updateProgressAfterReading && patch.isRead && manga.trackRecords.totalCount - ? manga.id - : undefined, - }, - { errorPolicy: 'all' }, - ) - .response.catch(defaultPromiseErrorHandler('ReaderService::useUpdateChapter')); + this.getOrCreateChapterUpdateQueue(currentChapter.id).enqueue(`${currentChapter.id}`, () => update()); }, [ manga?.id,