Skip to content

Commit

Permalink
Properly handle double spread offset
Browse files Browse the repository at this point in the history
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  |
  • Loading branch information
schroda committed Nov 8, 2024
1 parent e90d705 commit f88dda3
Showing 1 changed file with 43 additions and 26 deletions.
69 changes: 43 additions & 26 deletions src/modules/reader/components/pager/DoublePagedPager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* 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 { Page } from '@/modules/reader/components/page/Page.tsx';
import { IReaderProps } from '@/modules/reader/Reader.types.ts';
Expand All @@ -22,11 +22,17 @@ export function DoublePagedPager(props: IReaderProps) {
const selfRef = useRef<HTMLDivElement>(null);

const pagesToDisplayStateRef = useRef<boolean[]>([]);
const pageToPrevSpreadPageRef = useRef<number[]>([]);

const [pagesToSpreadState, setPagesToSpreadState] = useState(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() {
const setNextPage = (page: number) => setCurPage(page === -1 ? pages.length - 1 : page);

Expand Down Expand Up @@ -131,45 +137,56 @@ export function DoublePagedPager(props: IReaderProps) {
}}
>
{pages.map(({ index, src }) => {
const prevSpreadPage = (() => {
let currentIndexOfPrevSpreadPage = pageToPrevSpreadPageRef.current[curPage];
/*
if (currentIndexOfPrevSpreadPage === undefined) {
currentIndexOfPrevSpreadPage = Math.max(pagesToSpreadState.lastIndexOf(true, curPage), 0);
| = page separator
+ = double page
_ = double spread
const areAllPrevPagesLoaded = pagesLoadState.slice(0, curPage).every(Boolean);
if (areAllPrevPagesLoaded) {
pageToPrevSpreadPageRef.current[curPage] = currentIndexOfPrevSpreadPage;
}
}
without double spreads:
without double spread offset: | 0 + 1 | 2 + 3 | 4 + 5 | 6 + 7 | 8 |
with double spread offset : | 0 | 1 + 2 | 3 + 4 | 5 + 6 | 7 + 8 |
return currentIndexOfPrevSpreadPage > 0
? currentIndexOfPrevSpreadPage + 1
: currentIndexOfPrevSpreadPage;
})();
with double spreads
to handle double spreads:
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
// index of first page after a spread page will be 0
const normalizedCurPageIndexForSpreadPages = curPage - prevSpreadPage;
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 |
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);
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 normalizedCurPageIndex = normalizedCurPageIndexForSpreadPages - firstPageOffset;
const normalizedCurPage = pageToActualPageIndex[curPage];
const isCurPageEven = !(normalizedCurPage % 2);

const isCurPageEven = !(normalizedCurPageIndex % 2);
const secondPage = curPage + (isCurPageEven ? 1 : -1);
const secondPageOffset = (() => {
const invert = settings.offsetFirstPage ? -1 : 1;
const offset = isCurPageEven ? 1 : -1;

return offset * invert;
})();

const secondPage = curPage + secondPageOffset;

const isFirstPage = curPage === 0;
const isCurPage = index === curPage;
const isSecondPage = index === secondPage;

const isCurrentPageSpreadPage = pagesToSpreadState[curPage];
const isSecondPageSpreadPage = pagesToSpreadState[secondPage];
const hasSpreadPage = isCurrentPageSpreadPage || isSecondPageSpreadPage;

const displaySecondPage = isSecondPage && !hasSpreadPage;
const ignoreSecondPageDueToOffset = isFirstPage && settings.offsetFirstPage;

const displaySecondPage = isSecondPage && !hasSpreadPage && !ignoreSecondPageDueToOffset;
const displayPage = isCurPage || displaySecondPage;

pagesToDisplayStateRef.current[index] = displayPage;
Expand Down

0 comments on commit f88dda3

Please sign in to comment.