fix: implement viewport-based page navigation for EPUBs
- Replace spine-only navigation with scroll-based page navigation - nextPage: scroll down within chapter, only jump to next spine at chapter end - previousPage: scroll up within chapter, only jump to previous spine at chapter start - Use viewportHeight - 120 for accurate page height calculation - Fallback to spine-only navigation when page calculation not available
This commit is contained in:
@@ -22,31 +22,43 @@ export function createNavigationAPI() {
|
|||||||
readerEvents.emit("beforePageChange", state.currentReader);
|
readerEvents.emit("beforePageChange", state.currentReader);
|
||||||
|
|
||||||
if (state.currentReader.type === "ebook") {
|
if (state.currentReader.type === "ebook") {
|
||||||
if (
|
const container = document.getElementById("reader-content");
|
||||||
state.currentReader.currentSpineIndex <
|
const viewportHeightAdjusted = window.innerHeight - 120;
|
||||||
state.currentReader.cif.spine.length - 1
|
|
||||||
) {
|
if (pageCalculationResult) {
|
||||||
state.currentReader.currentSpineIndex++;
|
const currentChapter = pageCalculationResult.chapterMap.get(
|
||||||
if (pageCalculationResult) {
|
state.currentReader.currentSpineIndex,
|
||||||
const container = document.getElementById("reader-content");
|
);
|
||||||
if (container) {
|
|
||||||
const viewportHeight = window.innerHeight;
|
if (currentChapter && container) {
|
||||||
const target = getScrollPositionForPage(
|
const currentPageInChapter = Math.floor(
|
||||||
pageCalculationResult,
|
container.scrollTop / viewportHeightAdjusted,
|
||||||
state.currentReader.currentPage ||
|
);
|
||||||
state.currentReader.currentSpineIndex + 1,
|
const pagesInCurrentChapter =
|
||||||
viewportHeight,
|
currentChapter.endPage - currentChapter.startPage + 1;
|
||||||
);
|
|
||||||
if (
|
if (currentPageInChapter < pagesInCurrentChapter - 1) {
|
||||||
target &&
|
// Still pages left in current chapter - just scroll down
|
||||||
target.spineIndex !== state.currentReader.currentSpineIndex
|
container.scrollTop =
|
||||||
) {
|
(currentPageInChapter + 1) * viewportHeightAdjusted;
|
||||||
state.currentReader.currentSpineIndex = target.spineIndex;
|
} else if (
|
||||||
container.scrollTop = target.scrollTop;
|
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") {
|
} else if (state.currentReader.type === "pdf") {
|
||||||
const totalPages = state.readerMetadata?.total_pages || 0;
|
const totalPages = state.readerMetadata?.total_pages || 0;
|
||||||
@@ -80,28 +92,35 @@ export function createNavigationAPI() {
|
|||||||
readerEvents.emit("beforePageChange", state.currentReader);
|
readerEvents.emit("beforePageChange", state.currentReader);
|
||||||
|
|
||||||
if (state.currentReader.type === "ebook") {
|
if (state.currentReader.type === "ebook") {
|
||||||
if (state.currentReader.currentSpineIndex > 0) {
|
const container = document.getElementById("reader-content");
|
||||||
state.currentReader.currentSpineIndex--;
|
const viewportHeightAdjusted = window.innerHeight - 120;
|
||||||
if (pageCalculationResult) {
|
|
||||||
const container = document.getElementById("reader-content");
|
if (pageCalculationResult) {
|
||||||
if (container) {
|
const currentChapter = pageCalculationResult.chapterMap.get(
|
||||||
const viewportHeight = window.innerHeight;
|
state.currentReader.currentSpineIndex,
|
||||||
const target = getScrollPositionForPage(
|
);
|
||||||
pageCalculationResult,
|
|
||||||
state.currentReader.currentPage ||
|
if (currentChapter && container) {
|
||||||
state.currentReader.currentSpineIndex + 1,
|
const currentPageInChapter = Math.floor(
|
||||||
viewportHeight,
|
container.scrollTop / viewportHeightAdjusted,
|
||||||
);
|
);
|
||||||
if (
|
|
||||||
target &&
|
if (currentPageInChapter > 0) {
|
||||||
target.spineIndex !== state.currentReader.currentSpineIndex
|
// Not at start of chapter - just scroll up
|
||||||
) {
|
container.scrollTop =
|
||||||
state.currentReader.currentSpineIndex = target.spineIndex;
|
(currentPageInChapter - 1) * viewportHeightAdjusted;
|
||||||
container.scrollTop = target.scrollTop;
|
} 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") {
|
} else if (state.currentReader.type === "pdf") {
|
||||||
if (state.currentReader.currentPage > 1) {
|
if (state.currentReader.currentPage > 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user