Optionally adjust progress bar position based on available size
This commit is contained in:
@@ -939,6 +939,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"progress_bar": {
|
"progress_bar": {
|
||||||
|
"auto_vertical_position": {
|
||||||
|
"description": "Automatically change the progress bar to a vertical position depending on the available space",
|
||||||
|
"title": "Automatic progress bar vertical position"
|
||||||
|
},
|
||||||
"position": "Progress bar position",
|
"position": "Progress bar position",
|
||||||
"size": "Progress bar size",
|
"size": "Progress bar size",
|
||||||
"style": "Progress bar style"
|
"style": "Progress bar style"
|
||||||
|
|||||||
@@ -14,10 +14,16 @@ import { ButtonSelect } from '@/modules/core/components/buttons/ButtonSelect.tsx
|
|||||||
|
|
||||||
export const ButtonSelectInput = <Value extends string | number>({
|
export const ButtonSelectInput = <Value extends string | number>({
|
||||||
label,
|
label,
|
||||||
|
description,
|
||||||
...buttonSelectProps
|
...buttonSelectProps
|
||||||
}: ComponentProps<typeof ButtonSelect<Value>> & { label: string }) => (
|
}: ComponentProps<typeof ButtonSelect<Value>> & { label: string; description?: string }) => (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Typography>{label}</Typography>
|
<Typography>{label}</Typography>
|
||||||
|
{description && (
|
||||||
|
<Typography variant="body2" color="textDisabled">
|
||||||
|
{description}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
<ButtonSelect {...buttonSelectProps} />
|
<ButtonSelect {...buttonSelectProps} />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -263,7 +263,6 @@ export const ReaderProgressBar = withPropsFrom(
|
|||||||
'pageLoadStates',
|
'pageLoadStates',
|
||||||
'totalPages',
|
'totalPages',
|
||||||
'currentPageIndex',
|
'currentPageIndex',
|
||||||
'progressBarPosition',
|
|
||||||
'readingMode',
|
'readingMode',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { useReaderStateChaptersContext } from '@/modules/reader/contexts/state/R
|
|||||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||||
import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||||
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
|
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
|
||||||
import { ReaderResumeMode, ReaderStateChapters } from '@/modules/reader/types/Reader.types.ts';
|
import { ProgressBarPosition, ReaderResumeMode, ReaderStateChapters } from '@/modules/reader/types/Reader.types.ts';
|
||||||
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
||||||
import { useReaderProgressBarContext } from '@/modules/reader/contexts/ReaderProgressBarContext.tsx';
|
import { useReaderProgressBarContext } from '@/modules/reader/contexts/ReaderProgressBarContext.tsx';
|
||||||
import { useReaderOverlayContext } from '@/modules/reader/contexts/ReaderOverlayContext.tsx';
|
import { useReaderOverlayContext } from '@/modules/reader/contexts/ReaderOverlayContext.tsx';
|
||||||
@@ -147,6 +147,7 @@ const BaseMobileReaderProgressBar = ({
|
|||||||
{getOptionForDirection(<SkipPreviousIcon />, <SkipNextIcon />, direction)}
|
{getOptionForDirection(<SkipPreviousIcon />, <SkipNextIcon />, direction)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<ReaderProgressBar
|
<ReaderProgressBar
|
||||||
|
progressBarPosition={ProgressBarPosition.BOTTOM}
|
||||||
fullSegmentClicks={false}
|
fullSegmentClicks={false}
|
||||||
createProgressBarSlot={useCallback(
|
createProgressBarSlot={useCallback(
|
||||||
(page, pagesIndex, _2, _3, _4, _5, isTrailingPage, totalPages) => (
|
(page, pagesIndex, _2, _3, _4, _5, isTrailingPage, totalPages) => (
|
||||||
|
|||||||
@@ -7,11 +7,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback, useState } from 'react';
|
||||||
import { ReaderProgressBar } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx';
|
import { ReaderProgressBar } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx';
|
||||||
import { userReaderStatePagesContext } from '@/modules/reader/contexts/state/ReaderStatePagesContext.tsx';
|
import { userReaderStatePagesContext } from '@/modules/reader/contexts/state/ReaderStatePagesContext.tsx';
|
||||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||||
import { IReaderSettings, ProgressBarType, TReaderScrollbarContext } from '@/modules/reader/types/Reader.types.ts';
|
import {
|
||||||
|
IReaderSettings,
|
||||||
|
ProgressBarPosition,
|
||||||
|
ProgressBarPositionAutoVertical,
|
||||||
|
ProgressBarType,
|
||||||
|
TReaderScrollbarContext,
|
||||||
|
} from '@/modules/reader/types/Reader.types.ts';
|
||||||
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
|
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
|
||||||
import { getProgressBarPositionInfo } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
import { getProgressBarPositionInfo } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||||
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
||||||
@@ -22,6 +28,7 @@ import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContex
|
|||||||
import { useReaderProgressBarContext } from '@/modules/reader/contexts/ReaderProgressBarContext.tsx';
|
import { useReaderProgressBarContext } from '@/modules/reader/contexts/ReaderProgressBarContext.tsx';
|
||||||
import { useReaderScrollbarContext } from '@/modules/reader/contexts/ReaderScrollbarContext.tsx';
|
import { useReaderScrollbarContext } from '@/modules/reader/contexts/ReaderScrollbarContext.tsx';
|
||||||
import { ReaderProgressBarSlotDesktop } from '@/modules/reader/components/overlay/progress-bar/desktop/ReaderProgressBarSlotDesktop.tsx';
|
import { ReaderProgressBarSlotDesktop } from '@/modules/reader/components/overlay/progress-bar/desktop/ReaderProgressBarSlotDesktop.tsx';
|
||||||
|
import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx';
|
||||||
|
|
||||||
const BaseStandardReaderProgressBar = ({
|
const BaseStandardReaderProgressBar = ({
|
||||||
readerNavBarWidth,
|
readerNavBarWidth,
|
||||||
@@ -31,20 +38,37 @@ const BaseStandardReaderProgressBar = ({
|
|||||||
progressBarType,
|
progressBarType,
|
||||||
progressBarSize,
|
progressBarSize,
|
||||||
progressBarPosition,
|
progressBarPosition,
|
||||||
|
progressBarPositionAutoVertical,
|
||||||
readerDirection,
|
readerDirection,
|
||||||
scrollbarXSize,
|
scrollbarXSize,
|
||||||
scrollbarYSize,
|
scrollbarYSize,
|
||||||
totalPages,
|
totalPages,
|
||||||
}: Pick<NavbarContextType, 'readerNavBarWidth'> &
|
}: Pick<NavbarContextType, 'readerNavBarWidth'> &
|
||||||
Pick<TReaderProgressBarContext, 'isMaximized' | 'setIsMaximized' | 'isDragging'> &
|
Pick<TReaderProgressBarContext, 'isMaximized' | 'setIsMaximized' | 'isDragging'> &
|
||||||
Pick<IReaderSettings, 'progressBarType' | 'progressBarSize' | 'progressBarPosition'> &
|
Pick<
|
||||||
|
IReaderSettings,
|
||||||
|
'progressBarType' | 'progressBarSize' | 'progressBarPosition' | 'progressBarPositionAutoVertical'
|
||||||
|
> &
|
||||||
Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> &
|
Pick<TReaderScrollbarContext, 'scrollbarXSize' | 'scrollbarYSize'> &
|
||||||
Pick<ReaderProgressBarProps, 'totalPages'> & {
|
Pick<ReaderProgressBarProps, 'totalPages'> & {
|
||||||
readerDirection: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
readerDirection: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const { isBottom, isLeft, isRight, isVertical, isHorizontal } = getProgressBarPositionInfo(progressBarPosition);
|
const [, setRefreshProgressBarPosition] = useState({});
|
||||||
|
useResizeObserver(
|
||||||
|
window.document.documentElement,
|
||||||
|
useCallback(() => setRefreshProgressBarPosition({}), []),
|
||||||
|
);
|
||||||
|
|
||||||
|
const finalProgressBarPosition =
|
||||||
|
window.innerHeight > window.innerWidth &&
|
||||||
|
progressBarPositionAutoVertical !== ProgressBarPositionAutoVertical.OFF
|
||||||
|
? (progressBarPositionAutoVertical as unknown as ProgressBarPosition)
|
||||||
|
: progressBarPosition;
|
||||||
|
|
||||||
|
const { isBottom, isLeft, isRight, isVertical, isHorizontal } =
|
||||||
|
getProgressBarPositionInfo(finalProgressBarPosition);
|
||||||
|
|
||||||
const arePagesLoaded = !!totalPages;
|
const arePagesLoaded = !!totalPages;
|
||||||
const isHidden = progressBarType === ProgressBarType.HIDDEN;
|
const isHidden = progressBarType === ProgressBarType.HIDDEN;
|
||||||
@@ -55,6 +79,7 @@ const BaseStandardReaderProgressBar = ({
|
|||||||
return (
|
return (
|
||||||
<ReaderProgressBarDirectionWrapper>
|
<ReaderProgressBarDirectionWrapper>
|
||||||
<ReaderProgressBar
|
<ReaderProgressBar
|
||||||
|
progressBarPosition={finalProgressBarPosition}
|
||||||
fullSegmentClicks
|
fullSegmentClicks
|
||||||
createProgressBarSlot={useCallback(
|
createProgressBarSlot={useCallback(
|
||||||
(
|
(
|
||||||
@@ -73,13 +98,13 @@ const BaseStandardReaderProgressBar = ({
|
|||||||
pageUrl={page.primary.url}
|
pageUrl={page.primary.url}
|
||||||
primaryPageLoadState={primaryPageLoadState}
|
primaryPageLoadState={primaryPageLoadState}
|
||||||
secondaryPageLoadState={secondaryPageLoadState}
|
secondaryPageLoadState={secondaryPageLoadState}
|
||||||
progressBarPosition={progressBarPosition}
|
progressBarPosition={finalProgressBarPosition}
|
||||||
isCurrentPage={isCurrentPage}
|
isCurrentPage={isCurrentPage}
|
||||||
isLeadingPage={isLeadingPage}
|
isLeadingPage={isLeadingPage}
|
||||||
showDraggingStyle={showDraggingStyle}
|
showDraggingStyle={showDraggingStyle}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[progressBarPosition],
|
[finalProgressBarPosition],
|
||||||
)}
|
)}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
container: {
|
container: {
|
||||||
@@ -243,6 +268,7 @@ export const StandardReaderProgressBar = withPropsFrom(
|
|||||||
'progressBarType',
|
'progressBarType',
|
||||||
'progressBarSize',
|
'progressBarSize',
|
||||||
'progressBarPosition',
|
'progressBarPosition',
|
||||||
|
'progressBarPositionAutoVertical',
|
||||||
'readerDirection',
|
'readerDirection',
|
||||||
'scrollbarXSize',
|
'scrollbarXSize',
|
||||||
'scrollbarYSize',
|
'scrollbarYSize',
|
||||||
|
|||||||
@@ -52,9 +52,9 @@ export const ReaderGeneralSettings = ({
|
|||||||
onDefault={() => onDefault?.('progressBarSize')}
|
onDefault={() => onDefault?.('progressBarSize')}
|
||||||
/>
|
/>
|
||||||
<ReaderSettingProgressBarPosition
|
<ReaderSettingProgressBarPosition
|
||||||
overlayMode={overlayMode}
|
|
||||||
progressBarPosition={settings.progressBarPosition}
|
progressBarPosition={settings.progressBarPosition}
|
||||||
setProgressBarPosition={(value) => updateSetting('progressBarPosition', value)}
|
progressBarPositionAutoVertical={settings.progressBarPositionAutoVertical}
|
||||||
|
updateSetting={updateSetting}
|
||||||
/>
|
/>
|
||||||
{(settings.progressBarType === ProgressBarType.HIDDEN || overlayMode === ReaderOverlayMode.MOBILE) && (
|
{(settings.progressBarType === ProgressBarType.HIDDEN || overlayMode === ReaderOverlayMode.MOBILE) && (
|
||||||
<CheckboxInput
|
<CheckboxInput
|
||||||
|
|||||||
@@ -9,7 +9,12 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
||||||
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
|
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
|
||||||
import { IReaderSettings, ProgressBarPosition, ReaderOverlayMode } from '@/modules/reader/types/Reader.types.ts';
|
import NotInterestedIcon from '@mui/icons-material/NotInterested';
|
||||||
|
import {
|
||||||
|
IReaderSettings,
|
||||||
|
ProgressBarPosition,
|
||||||
|
ProgressBarPositionAutoVertical,
|
||||||
|
} from '@/modules/reader/types/Reader.types.ts';
|
||||||
import { ValueToDisplayData } from '@/modules/core/Core.types.ts';
|
import { ValueToDisplayData } from '@/modules/core/Core.types.ts';
|
||||||
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
import { ButtonSelectInput } from '@/modules/core/components/inputs/ButtonSelectInput.tsx';
|
||||||
|
|
||||||
@@ -30,26 +35,53 @@ const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ProgressBarPosition> = {
|
|||||||
|
|
||||||
const PROGRESS_BAR_POSITION_VALUES = Object.values(ProgressBarPosition).filter((value) => typeof value === 'number');
|
const PROGRESS_BAR_POSITION_VALUES = Object.values(ProgressBarPosition).filter((value) => typeof value === 'number');
|
||||||
|
|
||||||
|
const VALUE_TO_DISPLAY_DATA_AUTO_VERTICAL: ValueToDisplayData<ProgressBarPositionAutoVertical> = {
|
||||||
|
...VALUE_TO_DISPLAY_DATA,
|
||||||
|
[ProgressBarPositionAutoVertical.OFF]: {
|
||||||
|
title: 'global.label.disabled',
|
||||||
|
icon: <NotInterestedIcon />,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const PROGRESS_BAR_AUTO_VERTICAL_POSITION_VALUES = Object.values(ProgressBarPositionAutoVertical).filter(
|
||||||
|
(value) => typeof value === 'number',
|
||||||
|
);
|
||||||
|
|
||||||
export const ReaderSettingProgressBarPosition = ({
|
export const ReaderSettingProgressBarPosition = ({
|
||||||
overlayMode,
|
|
||||||
progressBarPosition,
|
progressBarPosition,
|
||||||
setProgressBarPosition,
|
progressBarPositionAutoVertical,
|
||||||
}: Pick<IReaderSettings, 'progressBarPosition' | 'overlayMode'> & {
|
updateSetting,
|
||||||
setProgressBarPosition: (position: ProgressBarPosition) => void;
|
}: Pick<IReaderSettings, 'progressBarPosition' | 'progressBarPositionAutoVertical'> & {
|
||||||
|
updateSetting: <
|
||||||
|
Position extends keyof Pick<IReaderSettings, 'progressBarPosition' | 'progressBarPositionAutoVertical'>,
|
||||||
|
>(
|
||||||
|
filter: Position,
|
||||||
|
value: IReaderSettings[Position],
|
||||||
|
) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (overlayMode !== ReaderOverlayMode.DESKTOP) {
|
const supportsAutoVerticalPosition = progressBarPosition === ProgressBarPosition.BOTTOM;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<ButtonSelectInput
|
<ButtonSelectInput
|
||||||
label={t('reader.settings.progress_bar.position')}
|
label={t('reader.settings.progress_bar.position')}
|
||||||
value={progressBarPosition}
|
value={progressBarPosition}
|
||||||
values={PROGRESS_BAR_POSITION_VALUES}
|
values={PROGRESS_BAR_POSITION_VALUES}
|
||||||
setValue={setProgressBarPosition}
|
setValue={(position) => updateSetting('progressBarPosition', position)}
|
||||||
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
|
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
|
||||||
/>
|
/>
|
||||||
|
{supportsAutoVerticalPosition && (
|
||||||
|
<ButtonSelectInput
|
||||||
|
label={t('reader.settings.progress_bar.auto_vertical_position.title')}
|
||||||
|
description={t('reader.settings.progress_bar.auto_vertical_position.description')}
|
||||||
|
value={progressBarPositionAutoVertical}
|
||||||
|
values={PROGRESS_BAR_AUTO_VERTICAL_POSITION_VALUES}
|
||||||
|
setValue={(position) => updateSetting('progressBarPositionAutoVertical', position)}
|
||||||
|
valueToDisplayData={VALUE_TO_DISPLAY_DATA_AUTO_VERTICAL}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ const GLOBAL_READER_SETTING_OBJECT: Record<keyof IReaderSettingsGlobal, undefine
|
|||||||
progressBarType: undefined,
|
progressBarType: undefined,
|
||||||
progressBarSize: undefined,
|
progressBarSize: undefined,
|
||||||
progressBarPosition: undefined,
|
progressBarPosition: undefined,
|
||||||
|
progressBarPositionAutoVertical: undefined,
|
||||||
shouldShowPageNumber: undefined,
|
shouldShowPageNumber: undefined,
|
||||||
isStaticNav: undefined,
|
isStaticNav: undefined,
|
||||||
backgroundColor: undefined,
|
backgroundColor: undefined,
|
||||||
@@ -73,6 +74,7 @@ export const DEFAULT_READER_SETTINGS: IReaderSettings = {
|
|||||||
progressBarType: ProgressBarType.STANDARD,
|
progressBarType: ProgressBarType.STANDARD,
|
||||||
progressBarSize: 4,
|
progressBarSize: 4,
|
||||||
progressBarPosition: ProgressBarPosition.BOTTOM,
|
progressBarPosition: ProgressBarPosition.BOTTOM,
|
||||||
|
progressBarPositionAutoVertical: ProgressBarPosition.RIGHT,
|
||||||
pageScaleMode: ReaderPageScaleMode.ORIGINAL,
|
pageScaleMode: ReaderPageScaleMode.ORIGINAL,
|
||||||
shouldStretchPage: false,
|
shouldStretchPage: false,
|
||||||
shouldOffsetDoubleSpreads: false,
|
shouldOffsetDoubleSpreads: false,
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ export enum ProgressBarPosition {
|
|||||||
RIGHT,
|
RIGHT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProgressBarPositionAutoVertical {
|
||||||
|
OFF = -1,
|
||||||
|
LEFT = ProgressBarPosition.LEFT,
|
||||||
|
RIGHT = ProgressBarPosition.RIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
export enum ReadingDirection {
|
export enum ReadingDirection {
|
||||||
LTR,
|
LTR,
|
||||||
RTL,
|
RTL,
|
||||||
@@ -119,6 +125,7 @@ export interface IReaderSettingsGlobal {
|
|||||||
*/
|
*/
|
||||||
progressBarSize: number;
|
progressBarSize: number;
|
||||||
progressBarPosition: ProgressBarPosition;
|
progressBarPosition: ProgressBarPosition;
|
||||||
|
progressBarPositionAutoVertical: ProgressBarPositionAutoVertical;
|
||||||
shouldShowPageNumber: boolean;
|
shouldShowPageNumber: boolean;
|
||||||
isStaticNav: boolean;
|
isStaticNav: boolean;
|
||||||
backgroundColor: ReaderBackgroundColor;
|
backgroundColor: ReaderBackgroundColor;
|
||||||
|
|||||||
Reference in New Issue
Block a user