diff --git a/web/src/reader/core/reader-navigation.ts b/web/src/reader/core/reader-navigation.ts index d0b0204..c648100 100644 --- a/web/src/reader/core/reader-navigation.ts +++ b/web/src/reader/core/reader-navigation.ts @@ -22,31 +22,43 @@ export function createNavigationAPI() { readerEvents.emit("beforePageChange", state.currentReader); if (state.currentReader.type === "ebook") { - if ( - state.currentReader.currentSpineIndex < - state.currentReader.cif.spine.length - 1 - ) { - state.currentReader.currentSpineIndex++; - if (pageCalculationResult) { - const container = document.getElementById("reader-content"); - if (container) { - const viewportHeight = window.innerHeight; - const target = getScrollPositionForPage( - pageCalculationResult, - state.currentReader.currentPage || - state.currentReader.currentSpineIndex + 1, - viewportHeight, - ); - if ( - target && - target.spineIndex !== state.currentReader.currentSpineIndex - ) { - state.currentReader.currentSpineIndex = target.spineIndex; - container.scrollTop = target.scrollTop; - } + const container = document.getElementById("reader-content"); + const viewportHeightAdjusted = window.innerHeight - 120; + + if (pageCalculationResult) { + const currentChapter = pageCalculationResult.chapterMap.get( + state.currentReader.currentSpineIndex, + ); + + if (currentChapter && container) { + const currentPageInChapter = Math.floor( + container.scrollTop / viewportHeightAdjusted, + ); + const pagesInCurrentChapter = + currentChapter.endPage - currentChapter.startPage + 1; + + if (currentPageInChapter < pagesInCurrentChapter - 1) { + // Still pages left in current chapter - just scroll down + container.scrollTop = + (currentPageInChapter + 1) * viewportHeightAdjusted; + } else if ( + state.currentReader.currentSpineIndex < + state.currentReader.cif.spine.length - 1 + ) { + // At end of chapter, move to next spine + state.currentReader.currentSpineIndex++; + renderSpineItem(); } } - renderSpineItem(); + } else { + // Fallback: just move to next spine + if ( + state.currentReader.currentSpineIndex < + state.currentReader.cif.spine.length - 1 + ) { + state.currentReader.currentSpineIndex++; + renderSpineItem(); + } } } else if (state.currentReader.type === "pdf") { const totalPages = state.readerMetadata?.total_pages || 0; @@ -80,28 +92,35 @@ export function createNavigationAPI() { readerEvents.emit("beforePageChange", state.currentReader); if (state.currentReader.type === "ebook") { - if (state.currentReader.currentSpineIndex > 0) { - state.currentReader.currentSpineIndex--; - if (pageCalculationResult) { - const container = document.getElementById("reader-content"); - if (container) { - const viewportHeight = window.innerHeight; - const target = getScrollPositionForPage( - pageCalculationResult, - state.currentReader.currentPage || - state.currentReader.currentSpineIndex + 1, - viewportHeight, - ); - if ( - target && - target.spineIndex !== state.currentReader.currentSpineIndex - ) { - state.currentReader.currentSpineIndex = target.spineIndex; - container.scrollTop = target.scrollTop; - } + const container = document.getElementById("reader-content"); + const viewportHeightAdjusted = window.innerHeight - 120; + + if (pageCalculationResult) { + const currentChapter = pageCalculationResult.chapterMap.get( + state.currentReader.currentSpineIndex, + ); + + if (currentChapter && container) { + const currentPageInChapter = Math.floor( + container.scrollTop / viewportHeightAdjusted, + ); + + if (currentPageInChapter > 0) { + // Not at start of chapter - just scroll up + container.scrollTop = + (currentPageInChapter - 1) * viewportHeightAdjusted; + } else if (state.currentReader.currentSpineIndex > 0) { + // At start of chapter, move to previous spine + state.currentReader.currentSpineIndex--; + renderSpineItem(); } } - renderSpineItem(); + } else { + // Fallback: just move to previous spine + if (state.currentReader.currentSpineIndex > 0) { + state.currentReader.currentSpineIndex--; + renderSpineItem(); + } } } else if (state.currentReader.type === "pdf") { if (state.currentReader.currentPage > 1) {