fix: clamp page numbers to content length and add fallback for missing images in Chapter view

This commit is contained in:
Rodrigo Verdiani 2026-05-08 11:34:54 -03:00
parent 96df79eaba
commit 8e221d01ab

View File

@ -48,10 +48,15 @@ const Chapter = () => {
/** Conflict Resolution & Initial Sync */
useEffect(() => {
if (isLoadingProgress || hasInitialized) return;
if (isLoadingProgress || !data?.data || hasInitialized) return;
const localPage = savedPage;
const serverPage = serverProgress?.pageNumber;
const images = data.data.contentImages;
const maxPages = images.length || 1;
const localPage = savedPage ? Math.min(savedPage, maxPages) : null;
const serverPage = serverProgress?.pageNumber
? Math.min(serverProgress.pageNumber, maxPages)
: null;
if (localPage === null) {
// No local history for this chapter, use server or default to 1
@ -87,7 +92,7 @@ const Chapter = () => {
}
setHasInitialized(true);
}
}, [isLoadingProgress, savedPage, serverProgress, hasInitialized]);
}, [isLoadingProgress, data, savedPage, serverProgress, hasInitialized]);
/** Mark chapter as read when last page reached */
useEffect(() => {
@ -269,10 +274,10 @@ const Chapter = () => {
this chapter.
<br />
<span className="mt-2 block">
Local: <strong>Page {savedPage}</strong>
Local: <strong>Page {savedPage ? Math.min(savedPage, images.length) : 1}</strong>
</span>
<span className="block">
Server: <strong>Page {serverProgress?.pageNumber}</strong>
Server: <strong>Page {serverProgress?.pageNumber ? Math.min(serverProgress.pageNumber, images.length) : 1}</strong>
</span>
</DialogDescription>
</DialogHeader>
@ -281,11 +286,12 @@ const Chapter = () => {
variant="outline"
onClick={() => {
if (savedPage && savedPage > 1) {
setCurrentPage(savedPage);
setVisibleCount(savedPage);
setIsAutoScrolling(true);
const clamped = Math.min(savedPage, images.length);
setCurrentPage(clamped);
setVisibleCount(clamped);
setIsAutoScrolling(clamped > 1);
initialJumpDone.current = false;
saveLocalProgress(savedPage, true);
saveLocalProgress(clamped, true);
}
setHasInitialized(true);
setShowConflictDialog(false);
@ -297,9 +303,10 @@ const Chapter = () => {
onClick={() => {
const target = applyServerProgress();
if (target) {
setCurrentPage(target);
setVisibleCount(target);
if (target > 1) {
const clamped = Math.min(target, images.length);
setCurrentPage(clamped);
setVisibleCount(clamped);
if (clamped > 1) {
setIsAutoScrolling(true);
initialJumpDone.current = false;
}
@ -480,13 +487,19 @@ const Chapter = () => {
/* MODE 2 --- STANDARD SINGLE-PAGE MODE */
/* ------------------------------------------------------------------ */
<>
<div className="relative mx-auto mb-8 overflow-hidden rounded-lg border border-border bg-muted">
<ChapterImage
imageKey={images[currentPage - 1].objectKey || ""}
uuid={images[currentPage - 1].uuid || ""}
pageNumber={currentPage}
priority
/>
<div className="relative mx-auto mb-8 overflow-hidden rounded-lg border border-border bg-muted min-h-[300px]">
{images[currentPage - 1] ? (
<ChapterImage
imageKey={images[currentPage - 1].objectKey || ""}
uuid={images[currentPage - 1].uuid || ""}
pageNumber={currentPage}
priority
/>
) : (
<div className="flex h-64 items-center justify-center">
<p className="text-muted-foreground">Page not found</p>
</div>
)}
</div>
{/* Preload next image */}