Skip to content

Commit

Permalink
Adding page loading with Double Page Mode. (Suwayomi#480)
Browse files Browse the repository at this point in the history
* page loading works and looks good now to make double page work with it

* Update double page spinner styling

* Render pages everytime the component gets rendered

- remove refs because they do not trigger a rerender
- remove initial render interval
- remove page rendering via portal

During the initial render nothing got rendered (pages or placeholder) because for that to happen, the images had to be loaded.
Thus, the loading placeholder never got shown.

* Enable skipping forward while pages are loading

---------

Co-authored-by: schroda <[email protected]>
  • Loading branch information
rickymcmuffin and schroda authored Jan 14, 2024
1 parent be5497a commit 9962e07
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 67 deletions.
43 changes: 36 additions & 7 deletions src/components/reader/DoublePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,39 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { forwardRef } from 'react';
import { Box, styled } from '@mui/material';
import { CSSProperties, forwardRef, useRef } from 'react';
import { Box, SxProps, Theme } from '@mui/material';
import { IReaderSettings } from '@/typings';
import { SpinnerImage } from '@/components/util/SpinnerImage';

const Image = styled('img')({
const imgStyles: CSSProperties = {
display: 'block',
marginBottom: 0,
width: 'auto',
minHeight: '99vh',
height: 'auto',
maxHeight: '99vh',
objectFit: 'contain',
});
};

const spinnerStyle: SxProps<Theme> = {
...imgStyles,
width: 'calc((100vw - 300px) * 0.5)',
backgroundColor: '#525252',
};

interface IProps {
index: number;
image1src: string;
image2src: string;
onImageLoad?: () => void;
settings: IReaderSettings;
}

export const DoublePage = forwardRef((props: IProps, ref: any) => {
const { image1src, image2src, index, settings } = props;
const { image1src, image2src, index, onImageLoad, settings } = props;

const imgRef = useRef<HTMLImageElement>(null);

return (
<Box
Expand All @@ -42,8 +53,26 @@ export const DoublePage = forwardRef((props: IProps, ref: any) => {
overflowX: 'scroll',
}}
>
<Image src={image1src} alt={`Page #${index}`} />
<Image src={image2src} alt={`Page #${index + 1}`} />
<SpinnerImage
src={image1src}
onImageLoad={onImageLoad}
alt={`Page #${index}`}
imgRef={imgRef}
spinnerStyle={spinnerStyle}
imgStyle={imgStyles}
/>
<SpinnerImage
src={image2src}
onImageLoad={onImageLoad}
alt={`Page #${index + 1}`}
imgRef={imgRef}
spinnerStyle={{
...spinnerStyle,
width: 'calc((100vw - 300px - 5px) * 0.5)',
marginLeft: '5px',
}}
imgStyle={imgStyles}
/>
</Box>
);
});
98 changes: 38 additions & 60 deletions src/components/reader/pager/DoublePagedPager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Box } from '@mui/material';
import { createRoot } from 'react-dom/client';
import { IReaderProps } from '@/typings';
import { Page } from '@/components/reader/Page';
import { DoublePage } from '@/components/reader/DoublePage';
Expand All @@ -35,56 +34,30 @@ export function DoublePagedPager(props: IReaderProps) {
const selfRef = useRef<HTMLDivElement>(null);
const pagesRef = useRef<HTMLImageElement[]>([]);

const pagesDisplayed = useRef<number>(0);
const pageLoaded = useRef<boolean[]>(Array(pages.length).fill(false));
const spreadPage = useRef<boolean[]>(Array(pages.length).fill(false));
const [pagesToSpreadState, setPagesToSpreadState] = useState(Array(pages.length).fill(false));
const [pagesLoadState, setPagesLoadState] = useState<boolean[]>(Array(pages.length).fill(false));

function setPagesToDisplay() {
pagesDisplayed.current = 0;
function getPagesToDisplay(): number {
let pagesToDisplay = 1; // has to be at least one so skipping forward while pages are still loading is possible
if (curPage < pages.length && pagesRef.current[curPage]) {
if (pageLoaded.current[curPage]) {
pagesDisplayed.current = 1;
if (spreadPage.current[curPage]) return;
if (pagesLoadState[curPage]) {
pagesToDisplay = 1;
if (pagesToSpreadState[curPage]) return pagesToDisplay;
}
}
if (curPage + 1 < pages.length && pagesRef.current[curPage + 1]) {
if (pageLoaded.current[curPage + 1]) {
if (isSinglePage(curPage, spreadPage.current, settings.offsetFirstPage)) return;
pagesDisplayed.current = 2;
if (pagesLoadState[curPage + 1]) {
if (isSinglePage(curPage, pagesToSpreadState, settings.offsetFirstPage)) return pagesToDisplay;
pagesToDisplay = 2;
}
}
}

function displayPages() {
const container = document.getElementById('display');
const root = createRoot(container!);

if (pagesDisplayed.current === 2) {
root.render(
<DoublePage
key={curPage}
index={curPage}
image1src={pages[curPage].src}
image2src={pages[curPage + 1].src}
settings={settings}
/>,
);
} else {
root.render(
<Page
key={curPage}
index={curPage}
src={pagesDisplayed.current === 1 ? pages[curPage].src : ''}
onImageLoad={() => {}}
settings={settings}
/>,
);
}
return pagesToDisplay;
}

function pagesToGoBack() {
// If previous page is single page, go only one page pack
if (isSinglePage(curPage - 2, spreadPage.current, settings.offsetFirstPage)) {
if (isSinglePage(curPage - 2, pagesToSpreadState, settings.offsetFirstPage)) {
return 1;
}

Expand All @@ -94,7 +67,7 @@ export function DoublePagedPager(props: IReaderProps) {

function nextPage() {
if (curPage < pages.length - 1) {
const nextCurPage = curPage + pagesDisplayed.current;
const nextCurPage = curPage + getPagesToDisplay();
setCurPage(nextCurPage >= pages.length ? pages.length - 1 : nextCurPage);
} else if (settings.loadNextOnEnding) {
nextChapter();
Expand Down Expand Up @@ -153,45 +126,32 @@ export function DoublePagedPager(props: IReaderProps) {

function handleImageLoad(index: number) {
return () => {
pageLoaded.current[index] = true;
setPagesLoadState((prevState) => prevState.toSpliced(index, 1, true));
const image = pagesRef.current[index];
spreadPage.current[index] = isSpreadPage(image);
setPagesToSpreadState((prevState) => prevState.toSpliced(index, 1, isSpreadPage(image)));
};
}

useEffect(() => {
const retryDisplay = setInterval(() => {
const isLastPage = curPage === pages.length - 1;
if (
(!isLastPage && pageLoaded.current[curPage] && pageLoaded.current[curPage + 1]) ||
pageLoaded.current[curPage]
) {
setPagesToDisplay();
displayPages();
clearInterval(retryDisplay);
}
}, 50);

document.addEventListener('keydown', keyboardControl);
selfRef.current?.addEventListener('click', clickControl);

return () => {
clearInterval(retryDisplay);
document.removeEventListener('keydown', keyboardControl);
selfRef.current?.removeEventListener('click', clickControl);
};
}, [selfRef, curPage, settings.readerType, prevChapter, nextChapter]);
}, [selfRef, curPage, settings.readerType, prevChapter, nextChapter, pagesLoadState, pagesToSpreadState]);

useEffect(() => {
setCurPage(initialPage);
}, [initialPage]);

useEffect(() => {
if (settings.offsetFirstPage) {
if (pagesDisplayed.current === 2) {
if (getPagesToDisplay() === 2) {
setCurPage(curPage + 1);
}
} else if (curPage > 0 && !isSinglePage(curPage - 1, spreadPage.current, settings.offsetFirstPage)) {
} else if (curPage > 0 && !isSinglePage(curPage - 1, pagesToSpreadState, settings.offsetFirstPage)) {
setCurPage(curPage - 1);
}
}, [settings.offsetFirstPage]);
Expand Down Expand Up @@ -222,7 +182,25 @@ export function DoublePagedPager(props: IReaderProps) {
height: 'auto',
overflowX: 'scroll',
}}
/>
>
{getPagesToDisplay() === 2 ? (
<DoublePage
key={curPage}
index={curPage}
image1src={pages[curPage].src}
image2src={pages[curPage + 1].src}
settings={settings}
/>
) : (
<Page
key={curPage}
index={curPage}
src={pages[curPage].src}
onImageLoad={() => {}}
settings={settings}
/>
)}
</Box>
</Box>
);
}

0 comments on commit 9962e07

Please sign in to comment.