feat: nextbook on next page if last page

This commit is contained in:
Julien Froidefond
2025-03-07 08:15:34 +01:00
parent 591a41149f
commit 66f467c66b
8 changed files with 66 additions and 10 deletions

View File

@@ -13,14 +13,16 @@ import { NavigationBar } from "./components/NavigationBar";
import { ControlButtons } from "./components/ControlButtons";
import { ReaderContent } from "./components/ReaderContent";
import { useReadingDirection } from "./hooks/useReadingDirection";
import { useTranslate } from "@/hooks/useTranslate";
export function BookReader({ book, pages, onClose }: BookReaderProps) {
export function BookReader({ book, pages, onClose, nextBook }: BookReaderProps) {
const [isDoublePage, setIsDoublePage] = useState(false);
const [showControls, setShowControls] = useState(false);
const readerRef = useRef<HTMLDivElement>(null);
const isLandscape = useOrientation();
const { direction, toggleDirection, isRTL } = useReadingDirection();
const { isFullscreen, toggleFullscreen } = useFullscreen();
const { t } = useTranslate();
const {
currentPage,
@@ -35,12 +37,14 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
zoomLevel,
panPosition,
handleDoubleClick,
showEndMessage,
} = usePageNavigation({
book,
pages,
isDoublePage,
onClose,
direction,
nextBook,
});
const { preloadPage, getPageUrl, cleanCache } = usePageCache({
@@ -92,6 +96,21 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
onClick={() => setShowControls(!showControls)}
>
<div className="relative h-full w-full flex items-center justify-center">
{showEndMessage && (
<div className="absolute inset-0 flex items-center justify-center bg-background/80 backdrop-blur-sm z-50">
<div className="bg-background border rounded-lg shadow-lg p-6 max-w-md text-center">
<h3 className="text-lg font-semibold mb-2">{t("reader.endOfSeries")}</h3>
<p className="text-muted-foreground mb-4">{t("reader.endOfSeriesMessage")}</p>
<button
onClick={() => onClose?.(currentPage)}
className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
>
{t("reader.backToSeries")}
</button>
</div>
</div>
)}
<ControlButtons
showControls={showControls}
onToggleControls={() => setShowControls(!showControls)}

View File

@@ -8,9 +8,10 @@ import { ClientOfflineBookService } from "@/lib/services/client-offlinebook.serv
interface ClientBookWrapperProps {
book: KomgaBook;
pages: number[];
nextBook: KomgaBook | null;
}
export function ClientBookWrapper({ book, pages }: ClientBookWrapperProps) {
export function ClientBookWrapper({ book, pages, nextBook }: ClientBookWrapperProps) {
const router = useRouter();
const handleCloseReader = (currentPage: number) => {
@@ -18,8 +19,9 @@ export function ClientBookWrapper({ book, pages }: ClientBookWrapperProps) {
method: "POST",
});
ClientOfflineBookService.setCurrentPage(book, currentPage);
router.back();
router.push(`/series/${book.seriesId}`);
//router.back();
};
return <BookReader book={book} pages={pages} onClose={handleCloseReader} />;
return <BookReader book={book} pages={pages} onClose={handleCloseReader} nextBook={nextBook} />;
}

View File

@@ -1,6 +1,7 @@
import { useState, useCallback, useEffect, useRef } from "react";
import type { KomgaBook } from "@/types/komga";
import { ClientOfflineBookService } from "@/lib/services/client-offlinebook.service";
import { useRouter } from "next/navigation";
interface UsePageNavigationProps {
book: KomgaBook;
@@ -8,6 +9,7 @@ interface UsePageNavigationProps {
isDoublePage: boolean;
onClose?: (currentPage: number) => void;
direction: "ltr" | "rtl";
nextBook?: KomgaBook | null;
}
export const usePageNavigation = ({
@@ -16,13 +18,16 @@ export const usePageNavigation = ({
isDoublePage,
onClose,
direction,
nextBook,
}: UsePageNavigationProps) => {
const router = useRouter();
const cPage = ClientOfflineBookService.getCurrentPage(book);
const [currentPage, setCurrentPage] = useState(cPage < 1 ? 1 : cPage);
const [isLoading, setIsLoading] = useState(true);
const [secondPageLoading, setSecondPageLoading] = useState(true);
const [zoomLevel, setZoomLevel] = useState(1);
const [panPosition, setPanPosition] = useState({ x: 0, y: 0 });
const [showEndMessage, setShowEndMessage] = useState(false);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const touchStartXRef = useRef<number | null>(null);
const touchStartYRef = useRef<number | null>(null);
@@ -107,13 +112,29 @@ export const usePageNavigation = ({
}, [currentPage, isDoublePage, navigateToPage, shouldShowDoublePage]);
const handleNextPage = useCallback(() => {
if (currentPage === pages.length) return;
if (currentPage === pages.length) {
if (nextBook) {
router.push(`/books/${nextBook.id}`);
return;
} else {
setShowEndMessage(true);
return;
}
}
if (isDoublePage && shouldShowDoublePage(currentPage)) {
navigateToPage(Math.min(pages.length, currentPage + 2));
} else {
navigateToPage(Math.min(pages.length, currentPage + 1));
}
}, [currentPage, isDoublePage, navigateToPage, pages.length, shouldShowDoublePage]);
}, [
currentPage,
isDoublePage,
navigateToPage,
pages.length,
shouldShowDoublePage,
nextBook,
router,
]);
const calculateDistance = (touch1: Touch, touch2: Touch) => {
const dx = touch2.clientX - touch1.clientX;
@@ -301,5 +322,6 @@ export const usePageNavigation = ({
zoomLevel,
panPosition,
handleDoubleClick,
showEndMessage,
};
};

View File

@@ -13,6 +13,7 @@ export interface BookReaderProps {
book: KomgaBook;
pages: number[];
onClose?: (currentPage: number) => void;
nextBook?: KomgaBook | null;
}
export interface ThumbnailProps {