Properly handle double spread offset
There were cases were a page after a double spread page was rendered twice. 1: | double spread page | 2: | page A | page B | 3: | page B | page C |
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MouseEvent, useEffect, useRef, useState } from 'react';
|
import { MouseEvent, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { Page } from '@/modules/reader/components/page/Page.tsx';
|
import { Page } from '@/modules/reader/components/page/Page.tsx';
|
||||||
import { IReaderProps } from '@/modules/reader/Reader.types.ts';
|
import { IReaderProps } from '@/modules/reader/Reader.types.ts';
|
||||||
@@ -22,11 +22,17 @@ export function DoublePagedPager(props: IReaderProps) {
|
|||||||
const selfRef = useRef<HTMLDivElement>(null);
|
const selfRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const pagesToDisplayStateRef = useRef<boolean[]>([]);
|
const pagesToDisplayStateRef = useRef<boolean[]>([]);
|
||||||
const pageToPrevSpreadPageRef = useRef<number[]>([]);
|
|
||||||
|
|
||||||
const [pagesToSpreadState, setPagesToSpreadState] = useState(Array(pages.length).fill(false));
|
const [pagesToSpreadState, setPagesToSpreadState] = useState(Array(pages.length).fill(false));
|
||||||
const [pagesLoadState, setPagesLoadState] = useState<boolean[]>(Array(pages.length).fill(false));
|
const [pagesLoadState, setPagesLoadState] = useState<boolean[]>(Array(pages.length).fill(false));
|
||||||
|
|
||||||
|
// each spread page has to be counted as 2 pages and all trailing page numbers have to be increased by the count
|
||||||
|
// of leading spread pages
|
||||||
|
const pageToActualPageIndex = useMemo(
|
||||||
|
() => pagesToSpreadState.map((_, page) => page + pagesToSpreadState.slice(0, page).filter(Boolean).length),
|
||||||
|
[pagesToSpreadState],
|
||||||
|
);
|
||||||
|
|
||||||
function nextPage() {
|
function nextPage() {
|
||||||
const setNextPage = (page: number) => setCurPage(page === -1 ? pages.length - 1 : page);
|
const setNextPage = (page: number) => setCurPage(page === -1 ? pages.length - 1 : page);
|
||||||
|
|
||||||
@@ -131,37 +137,46 @@ export function DoublePagedPager(props: IReaderProps) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pages.map(({ index, src }) => {
|
{pages.map(({ index, src }) => {
|
||||||
const prevSpreadPage = (() => {
|
/*
|
||||||
let currentIndexOfPrevSpreadPage = pageToPrevSpreadPageRef.current[curPage];
|
|
||||||
|
|
||||||
if (currentIndexOfPrevSpreadPage === undefined) {
|
| = page separator
|
||||||
currentIndexOfPrevSpreadPage = Math.max(pagesToSpreadState.lastIndexOf(true, curPage), 0);
|
+ = double page
|
||||||
|
_ = double spread
|
||||||
|
|
||||||
const areAllPrevPagesLoaded = pagesLoadState.slice(0, curPage).every(Boolean);
|
without double spreads:
|
||||||
if (areAllPrevPagesLoaded) {
|
without double spread offset: | 0 + 1 | 2 + 3 | 4 + 5 | 6 + 7 | 8 |
|
||||||
pageToPrevSpreadPageRef.current[curPage] = currentIndexOfPrevSpreadPage;
|
with double spread offset : | 0 | 1 + 2 | 3 + 4 | 5 + 6 | 7 + 8 |
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentIndexOfPrevSpreadPage > 0
|
with double spreads
|
||||||
? currentIndexOfPrevSpreadPage + 1
|
to handle double spreads:
|
||||||
: currentIndexOfPrevSpreadPage;
|
each double spread has to count as 2 pages, thus, each page number after a double spread has to increase
|
||||||
|
by the number of leading double spreads
|
||||||
|
|
||||||
|
without double spread offset: | 0 + 1 | 2 | _3/4_ | 5 + 6 | 7 + 8 | _9/10_ | 11 + 12 | 13 + 14 |
|
||||||
|
with double spread offset : | 0 | 1 + 2 | _3/4_ | 5 + 6 | 7 + 8 | _9/10_ | 11 + 12 | 13 + 14 |
|
||||||
|
|
||||||
|
thus, to get the second page:
|
||||||
|
without offset: second page = current page number even ? +1 : -1
|
||||||
|
with offset : second page = current page number even ? +1 : -1
|
||||||
|
|
||||||
|
the second page has to be ignored in case:
|
||||||
|
- double spreads are offset, and the current page is the first page
|
||||||
|
- either the current or second page is a double spread
|
||||||
|
*/
|
||||||
|
|
||||||
|
const normalizedCurPage = pageToActualPageIndex[curPage];
|
||||||
|
const isCurPageEven = !(normalizedCurPage % 2);
|
||||||
|
|
||||||
|
const secondPageOffset = (() => {
|
||||||
|
const invert = settings.offsetFirstPage ? -1 : 1;
|
||||||
|
const offset = isCurPageEven ? 1 : -1;
|
||||||
|
|
||||||
|
return offset * invert;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// index of first page after a spread page will be 0
|
const secondPage = curPage + secondPageOffset;
|
||||||
const normalizedCurPageIndexForSpreadPages = curPage - prevSpreadPage;
|
|
||||||
|
|
||||||
const isFirstPage = curPage === 0;
|
const isFirstPage = curPage === 0;
|
||||||
// only offset pages before the first spread page, after the first spread page handle as if "offsetFirstPage" is disabled
|
|
||||||
const firstPageOffset =
|
|
||||||
Number(settings.offsetFirstPage) +
|
|
||||||
Number(settings.offsetFirstPage && !normalizedCurPageIndexForSpreadPages && !isFirstPage);
|
|
||||||
|
|
||||||
const normalizedCurPageIndex = normalizedCurPageIndexForSpreadPages - firstPageOffset;
|
|
||||||
|
|
||||||
const isCurPageEven = !(normalizedCurPageIndex % 2);
|
|
||||||
const secondPage = curPage + (isCurPageEven ? 1 : -1);
|
|
||||||
|
|
||||||
const isCurPage = index === curPage;
|
const isCurPage = index === curPage;
|
||||||
const isSecondPage = index === secondPage;
|
const isSecondPage = index === secondPage;
|
||||||
|
|
||||||
@@ -169,7 +184,9 @@ export function DoublePagedPager(props: IReaderProps) {
|
|||||||
const isSecondPageSpreadPage = pagesToSpreadState[secondPage];
|
const isSecondPageSpreadPage = pagesToSpreadState[secondPage];
|
||||||
const hasSpreadPage = isCurrentPageSpreadPage || isSecondPageSpreadPage;
|
const hasSpreadPage = isCurrentPageSpreadPage || isSecondPageSpreadPage;
|
||||||
|
|
||||||
const displaySecondPage = isSecondPage && !hasSpreadPage;
|
const ignoreSecondPageDueToOffset = isFirstPage && settings.offsetFirstPage;
|
||||||
|
|
||||||
|
const displaySecondPage = isSecondPage && !hasSpreadPage && !ignoreSecondPageDueToOffset;
|
||||||
const displayPage = isCurPage || displaySecondPage;
|
const displayPage = isCurPage || displaySecondPage;
|
||||||
|
|
||||||
pagesToDisplayStateRef.current[index] = displayPage;
|
pagesToDisplayStateRef.current[index] = displayPage;
|
||||||
|
|||||||
Reference in New Issue
Block a user