Fix reader width (#567)
* Fix reader width The margin: auto on the Box container for the image was preventing 100% width to actually mean 100%. Now that 100% is actually possible, I think fitPageToWindow makes more sense as a default. Additionally, since the image can fill 100% of the page, it can cover the ReaderNavBar, so set the z-index of the ReaderNavBar so it's rendered on top of the image and clickable. Signed-off-by: Chance Zibolski <chance.zibolski@gmail.com> * Support configuring reader width for DoublePage readers Signed-off-by: Chance Zibolski <chance.zibolski@gmail.com> * Fix single page of DoublePageReader not being able to take up full width In case the parent container is flex row, the container does not automatically take up 100% of the available width, thus, the page also was not able to take up 100% of the width * Fix applying reader width to double pages The set reader width can't be applied to each page of the double pages because otherwise it will already take up 100% of the available width with the setting only being at 50%. Instead, the set width has to be divided by 2, so that both pages take up the set reader width * Prevent double page spinner from being larger than 100% of the available width * Update width styling of the page spinner * Always center pages in the middle of the screen * Take up full height fitting page to window height --------- Signed-off-by: Chance Zibolski <chance.zibolski@gmail.com> Co-authored-by: schroda <50052685+schroda@users.noreply.github.com>
This commit is contained in:
@@ -26,7 +26,11 @@ import { useTranslation } from 'react-i18next';
|
||||
import { AllowedMetadataValueTypes, ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings';
|
||||
import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions';
|
||||
|
||||
const Root = styled('div')(({ theme }) => ({
|
||||
const Root = styled('div')({
|
||||
zIndex: 10,
|
||||
});
|
||||
|
||||
const NavContainer = styled('div')(({ theme }) => ({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '300px',
|
||||
@@ -198,9 +202,9 @@ export function ReaderNavBar(props: IProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Root>
|
||||
<Slide direction="right" in={drawerOpen} timeout={200} appear={false} mountOnEnter unmountOnExit>
|
||||
<Root
|
||||
<NavContainer
|
||||
sx={{
|
||||
position: 'fixed',
|
||||
}}
|
||||
@@ -374,7 +378,7 @@ export function ReaderNavBar(props: IProps) {
|
||||
</Tooltip>
|
||||
</ChapterNavigation>
|
||||
</Navigation>
|
||||
</Root>
|
||||
</NavContainer>
|
||||
</Slide>
|
||||
<Zoom in={!drawerOpen}>
|
||||
<Fade in={!hideOpenButton}>
|
||||
@@ -392,6 +396,6 @@ export function ReaderNavBar(props: IProps) {
|
||||
</Tooltip>
|
||||
</Fade>
|
||||
</Zoom>
|
||||
</>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,26 +6,11 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { CSSProperties, forwardRef, useRef } from 'react';
|
||||
import { forwardRef, useRef } from 'react';
|
||||
import { Box, SxProps, Theme } from '@mui/material';
|
||||
import { IReaderSettings } from '@/typings';
|
||||
import { SpinnerImage } from '@/components/util/SpinnerImage';
|
||||
|
||||
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',
|
||||
};
|
||||
import { imageStyle } from '@/components/reader/Page';
|
||||
|
||||
interface IProps {
|
||||
index: number;
|
||||
@@ -39,18 +24,26 @@ export const DoublePage = forwardRef((props: IProps, ref: any) => {
|
||||
const { image1src, image2src, index, onImageLoad, settings } = props;
|
||||
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
const baseImgStyle = imageStyle(settings);
|
||||
const imgStyle = {
|
||||
...baseImgStyle,
|
||||
width: settings.fitPageToWindow ? baseImgStyle.width : `calc(${baseImgStyle.width} * 0.5)`,
|
||||
};
|
||||
|
||||
const spinnerStyle: SxProps<Theme> = {
|
||||
...imgStyle,
|
||||
height: '100vh',
|
||||
width: '50%',
|
||||
backgroundColor: '#525252',
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={ref}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: settings.readerType === 'DoubleLTR' ? 'row' : 'row-reverse',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
overflowX: 'scroll',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<SpinnerImage
|
||||
@@ -59,7 +52,7 @@ export const DoublePage = forwardRef((props: IProps, ref: any) => {
|
||||
alt={`Page #${index}`}
|
||||
imgRef={imgRef}
|
||||
spinnerStyle={spinnerStyle}
|
||||
imgStyle={imgStyles}
|
||||
imgStyle={imgStyle}
|
||||
/>
|
||||
<SpinnerImage
|
||||
src={image2src}
|
||||
@@ -68,10 +61,10 @@ export const DoublePage = forwardRef((props: IProps, ref: any) => {
|
||||
imgRef={imgRef}
|
||||
spinnerStyle={{
|
||||
...spinnerStyle,
|
||||
width: 'calc((100vw - 300px - 5px) * 0.5)',
|
||||
width: 'calc(50% - 5px)',
|
||||
marginLeft: '5px',
|
||||
}}
|
||||
imgStyle={imgStyles}
|
||||
imgStyle={imgStyle}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
|
||||
import { useState, useEffect, forwardRef, useRef } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useMediaQuery } from '@mui/material';
|
||||
import { IReaderSettings, ReaderType } from '@/typings';
|
||||
import { SpinnerImage } from '@/components/util/SpinnerImage';
|
||||
|
||||
export const isFillsPageReaderType = (readerType: ReaderType): boolean =>
|
||||
['DoubleRTL', 'DoubleLTR', 'ContinuesHorizontalLTR', 'ContinuesHorizontalRTL'].includes(readerType);
|
||||
export const isHorizontalReaderType = (readerType: ReaderType): boolean =>
|
||||
['ContinuesHorizontalLTR', 'ContinuesHorizontalRTL'].includes(readerType);
|
||||
|
||||
function imageStyle(settings: IReaderSettings): any {
|
||||
export function imageStyle(settings: IReaderSettings): any {
|
||||
const [dimensions, setDimensions] = useState({
|
||||
height: window.innerHeight,
|
||||
width: window.innerWidth,
|
||||
@@ -32,27 +34,26 @@ function imageStyle(settings: IReaderSettings): any {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, []);
|
||||
if (settings.fitPageToWindow || isFillsPageReaderType(settings.readerType)) {
|
||||
|
||||
const isHorizontal = isHorizontalReaderType(settings.readerType);
|
||||
if (settings.fitPageToWindow || isHorizontal) {
|
||||
return {
|
||||
display: 'block',
|
||||
marginLeft: '7px',
|
||||
marginRight: '7px',
|
||||
marginLeft: isHorizontal ? '7px' : 0,
|
||||
marginRight: isHorizontal ? '7px' : 0,
|
||||
width: 'auto',
|
||||
minHeight: '99vh',
|
||||
minHeight: '100vh',
|
||||
height: 'auto',
|
||||
maxHeight: '99vh',
|
||||
maxHeight: '100vh',
|
||||
objectFit: 'contain',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
display: 'block',
|
||||
marginBottom: settings.readerType === 'ContinuesVertical' ? '15px' : 0,
|
||||
minWidth: '10vw',
|
||||
width: dimensions.width < dimensions.height ? '100vw' : `${settings.readerWidth}%`,
|
||||
maxWidth: '100%',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
objectFit: 'contain',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,12 +67,19 @@ interface IProps {
|
||||
export const Page = forwardRef((props: IProps, ref: any) => {
|
||||
const { src, index, onImageLoad, settings } = props;
|
||||
|
||||
const theme = useTheme();
|
||||
const isMobileWidth = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
|
||||
const imgStyle = imageStyle(settings);
|
||||
const isDoublePageReader = ['DoubleRTL', 'DoubleLTR'].includes(settings.readerType);
|
||||
|
||||
return (
|
||||
<Box ref={ref} sx={{ margin: 'auto' }}>
|
||||
<Box
|
||||
ref={ref}
|
||||
sx={{ display: 'flex', justifyContent: 'center', minWidth: isDoublePageReader ? '100%' : undefined }}
|
||||
>
|
||||
<SpinnerImage
|
||||
src={src}
|
||||
onImageLoad={onImageLoad}
|
||||
@@ -80,7 +88,7 @@ export const Page = forwardRef((props: IProps, ref: any) => {
|
||||
spinnerStyle={{
|
||||
...imgStyle,
|
||||
height: '100vh',
|
||||
width: '70vw',
|
||||
width: isMobileWidth ? '100vw' : 'calc(100% * 0.5)',
|
||||
backgroundColor: '#525252',
|
||||
}}
|
||||
imgStyle={imgStyle}
|
||||
|
||||
@@ -12,7 +12,7 @@ import MenuItem from '@mui/material/MenuItem';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AllowedMetadataValueTypes, IReaderSettings } from '@/typings';
|
||||
import { NumberSetting } from '@/components/settings/NumberSetting.tsx';
|
||||
import { isFillsPageReaderType } from '@/components/reader/Page.tsx';
|
||||
import { isHorizontalReaderType } from '@/components/reader/Page.tsx';
|
||||
|
||||
interface IProps extends IReaderSettings {
|
||||
setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes) => void;
|
||||
@@ -30,7 +30,7 @@ export function ReaderSettingsOptions({
|
||||
readerWidth,
|
||||
}: IProps) {
|
||||
const { t } = useTranslation();
|
||||
const fitPageToWindowEligible = !isFillsPageReaderType(readerType);
|
||||
const fitPageToWindowEligible = !isHorizontalReaderType(readerType);
|
||||
return (
|
||||
<List>
|
||||
<ListItem>
|
||||
|
||||
@@ -175,10 +175,8 @@ export function DoublePagedPager(props: IReaderProps) {
|
||||
display: 'flex',
|
||||
flexDirection: settings.readerType === 'DoubleLTR' ? 'row' : 'row-reverse',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
overflowX: 'scroll',
|
||||
}}
|
||||
>
|
||||
{getPagesToDisplay() === 2 ? (
|
||||
|
||||
@@ -166,7 +166,6 @@ export function HorizontalPager(props: IReaderProps) {
|
||||
display: 'flex',
|
||||
flexDirection: settings.readerType === 'ContinuesHorizontalLTR' ? 'row' : 'row-reverse',
|
||||
justifyContent: settings.readerType === 'ContinuesHorizontalLTR' ? 'flex-start' : 'flex-end',
|
||||
margin: '0 auto',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
overflowX: 'visible',
|
||||
|
||||
@@ -99,11 +99,10 @@ export function PagedPager(props: IReaderProps) {
|
||||
ref={selfRef}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
width: '100%',
|
||||
height: '100vh',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
}}
|
||||
onClick={clickControl}
|
||||
>
|
||||
|
||||
@@ -173,8 +173,8 @@ export function VerticalPager(props: IReaderProps) {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
width: '100%',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -400,7 +400,12 @@ export function Reader() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
width: settings.staticNav ? 'calc(100vw - 300px)' : '100vw',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignContent: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: settings.staticNav ? 'calc((100vw - (100vw - 100%)) - 300px)' : '100vw - (100vw - 100%)', // 100vw = width excluding scrollbar; 100% = width including scrollbar
|
||||
minHeight: '100vh',
|
||||
marginLeft: settings.staticNav ? '300px' : 'unset',
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -25,7 +25,7 @@ export const getDefaultSettings = (): IReaderSettings => ({
|
||||
showPageNumber: true,
|
||||
loadNextOnEnding: false,
|
||||
skipDupChapters: true,
|
||||
fitPageToWindow: false,
|
||||
fitPageToWindow: true,
|
||||
readerType: 'ContinuesVertical',
|
||||
offsetFirstPage: false,
|
||||
readerWidth: 100,
|
||||
|
||||
Reference in New Issue
Block a user