/* * Copyright (C) Contributors to the Suwayomi project * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import React, { useEffect, useRef } from 'react'; import ReactDOM from 'react-dom'; import { Box } from '@mui/system'; import Page from '../Page'; import DoublePage from '../DoublePage'; export default function DoublePagedPager(props: IReaderProps) { const { pages, settings, setCurPage, curPage, nextChapter, prevChapter, } = props; const selfRef = useRef(null); const pagesRef = useRef([]); const pagesDisplayed = useRef(0); const pageLoaded = useRef(Array(pages.length).fill(false)); function setPagesToDisplay() { pagesDisplayed.current = 0; if (curPage < pages.length && pagesRef.current[curPage]) { if (pageLoaded.current[curPage]) { pagesDisplayed.current = 1; const imgElem = pagesRef.current[curPage]; const aspectRatio = imgElem.height / imgElem.width; if (aspectRatio < 1) { return; } } } if (curPage + 1 < pages.length && pagesRef.current[curPage + 1]) { if (pageLoaded.current[curPage + 1]) { const imgElem = pagesRef.current[curPage + 1]; const aspectRatio = imgElem.height / imgElem.width; if (aspectRatio < 1) { return; } pagesDisplayed.current = 2; } } } function displayPages() { if (pagesDisplayed.current === 2) { ReactDOM.render( , document.getElementById('display'), ); } else { ReactDOM.render( {}} setCurPage={setCurPage} settings={settings} />, document.getElementById('display'), ); } } function pagesToGoBack() { for (let i = 1; i <= 2; i++) { if (curPage - i > 0 && pagesRef.current[curPage - i]) { if (pageLoaded.current[curPage - i]) { const imgElem = pagesRef.current[curPage - i]; const aspectRatio = imgElem.height / imgElem.width; if (aspectRatio < 1) { return 1; } } } } return 2; } function nextPage() { if (curPage < pages.length - 1) { const nextCurPage = curPage + pagesDisplayed.current; setCurPage((nextCurPage >= pages.length) ? pages.length - 1 : nextCurPage); } else if (settings.loadNextonEnding) { nextChapter(); } } function prevPage() { if (curPage > 0) { const nextCurPage = curPage - pagesToGoBack(); setCurPage((nextCurPage < 0) ? 0 : nextCurPage); } else { prevChapter(); } } function goLeft() { if (settings.readerType === 'DoubleLTR') { prevPage(); } else { nextPage(); } } function goRight() { if (settings.readerType === 'DoubleLTR') { nextPage(); } else { prevPage(); } } function keyboardControl(e:KeyboardEvent) { switch (e.code) { case 'Space': e.preventDefault(); nextPage(); break; case 'ArrowRight': goRight(); break; case 'ArrowLeft': goLeft(); break; default: break; } } function clickControl(e:MouseEvent) { if (e.clientX > window.innerWidth / 2) { goRight(); } else { goLeft(); } } function handleImageLoad(index: number) { return () => { pageLoaded.current[index] = true; }; } 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]); return ( { pages.map((page) => ( { pagesRef.current[page.index] = e; }} key={`${page.index}`} src={page.src} onLoad={handleImageLoad(page.index)} alt={`${page.index}`} /> )) } ); }