diff --git a/public/locales/en.json b/public/locales/en.json index e6a31023..258f84e6 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -939,6 +939,10 @@ } }, "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", "size": "Progress bar size", "style": "Progress bar style" diff --git a/src/modules/core/components/inputs/ButtonSelectInput.tsx b/src/modules/core/components/inputs/ButtonSelectInput.tsx index 4517817b..4464632e 100644 --- a/src/modules/core/components/inputs/ButtonSelectInput.tsx +++ b/src/modules/core/components/inputs/ButtonSelectInput.tsx @@ -14,10 +14,16 @@ import { ButtonSelect } from '@/modules/core/components/buttons/ButtonSelect.tsx export const ButtonSelectInput = ({ label, + description, ...buttonSelectProps -}: ComponentProps> & { label: string }) => ( +}: ComponentProps> & { label: string; description?: string }) => ( {label} + {description && ( + + {description} + + )} ); diff --git a/src/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx b/src/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx index a17c0719..35141496 100644 --- a/src/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx +++ b/src/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx @@ -263,7 +263,6 @@ export const ReaderProgressBar = withPropsFrom( 'pageLoadStates', 'totalPages', 'currentPageIndex', - 'progressBarPosition', 'readingMode', ], ); diff --git a/src/modules/reader/components/overlay/progress-bar/variants/MobileReaderProgressBar.tsx b/src/modules/reader/components/overlay/progress-bar/variants/MobileReaderProgressBar.tsx index 646742fc..41c06b75 100644 --- a/src/modules/reader/components/overlay/progress-bar/variants/MobileReaderProgressBar.tsx +++ b/src/modules/reader/components/overlay/progress-bar/variants/MobileReaderProgressBar.tsx @@ -18,7 +18,7 @@ import { useReaderStateChaptersContext } from '@/modules/reader/contexts/state/R import { ReaderService } from '@/modules/reader/services/ReaderService.ts'; import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx'; 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 { useReaderProgressBarContext } from '@/modules/reader/contexts/ReaderProgressBarContext.tsx'; import { useReaderOverlayContext } from '@/modules/reader/contexts/ReaderOverlayContext.tsx'; @@ -147,6 +147,7 @@ const BaseMobileReaderProgressBar = ({ {getOptionForDirection(, , direction)} ( diff --git a/src/modules/reader/components/overlay/progress-bar/variants/StandardReaderProgressBar.tsx b/src/modules/reader/components/overlay/progress-bar/variants/StandardReaderProgressBar.tsx index fc951087..74e35787 100644 --- a/src/modules/reader/components/overlay/progress-bar/variants/StandardReaderProgressBar.tsx +++ b/src/modules/reader/components/overlay/progress-bar/variants/StandardReaderProgressBar.tsx @@ -7,11 +7,17 @@ */ 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 { userReaderStatePagesContext } from '@/modules/reader/contexts/state/ReaderStatePagesContext.tsx'; 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 { getProgressBarPositionInfo } from '@/modules/reader/utils/ReaderProgressBar.utils.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 { useReaderScrollbarContext } from '@/modules/reader/contexts/ReaderScrollbarContext.tsx'; import { ReaderProgressBarSlotDesktop } from '@/modules/reader/components/overlay/progress-bar/desktop/ReaderProgressBarSlotDesktop.tsx'; +import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx'; const BaseStandardReaderProgressBar = ({ readerNavBarWidth, @@ -31,20 +38,37 @@ const BaseStandardReaderProgressBar = ({ progressBarType, progressBarSize, progressBarPosition, + progressBarPositionAutoVertical, readerDirection, scrollbarXSize, scrollbarYSize, totalPages, }: Pick & Pick & - Pick & + Pick< + IReaderSettings, + 'progressBarType' | 'progressBarSize' | 'progressBarPosition' | 'progressBarPositionAutoVertical' + > & Pick & Pick & { readerDirection: ReturnType; }) => { 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 isHidden = progressBarType === ProgressBarType.HIDDEN; @@ -55,6 +79,7 @@ const BaseStandardReaderProgressBar = ({ return ( ), - [progressBarPosition], + [finalProgressBarPosition], )} slotProps={{ container: { @@ -243,6 +268,7 @@ export const StandardReaderProgressBar = withPropsFrom( 'progressBarType', 'progressBarSize', 'progressBarPosition', + 'progressBarPositionAutoVertical', 'readerDirection', 'scrollbarXSize', 'scrollbarYSize', diff --git a/src/modules/reader/components/settings/general/ReaderGeneralSettings.tsx b/src/modules/reader/components/settings/general/ReaderGeneralSettings.tsx index 4a248df9..1f470eb9 100644 --- a/src/modules/reader/components/settings/general/ReaderGeneralSettings.tsx +++ b/src/modules/reader/components/settings/general/ReaderGeneralSettings.tsx @@ -52,9 +52,9 @@ export const ReaderGeneralSettings = ({ onDefault={() => onDefault?.('progressBarSize')} /> updateSetting('progressBarPosition', value)} + progressBarPositionAutoVertical={settings.progressBarPositionAutoVertical} + updateSetting={updateSetting} /> {(settings.progressBarType === ProgressBarType.HIDDEN || overlayMode === ReaderOverlayMode.MOBILE) && ( = { const PROGRESS_BAR_POSITION_VALUES = Object.values(ProgressBarPosition).filter((value) => typeof value === 'number'); +const VALUE_TO_DISPLAY_DATA_AUTO_VERTICAL: ValueToDisplayData = { + ...VALUE_TO_DISPLAY_DATA, + [ProgressBarPositionAutoVertical.OFF]: { + title: 'global.label.disabled', + icon: , + }, +}; + +const PROGRESS_BAR_AUTO_VERTICAL_POSITION_VALUES = Object.values(ProgressBarPositionAutoVertical).filter( + (value) => typeof value === 'number', +); + export const ReaderSettingProgressBarPosition = ({ - overlayMode, progressBarPosition, - setProgressBarPosition, -}: Pick & { - setProgressBarPosition: (position: ProgressBarPosition) => void; + progressBarPositionAutoVertical, + updateSetting, +}: Pick & { + updateSetting: < + Position extends keyof Pick, + >( + filter: Position, + value: IReaderSettings[Position], + ) => void; }) => { const { t } = useTranslation(); - if (overlayMode !== ReaderOverlayMode.DESKTOP) { - return null; - } + const supportsAutoVerticalPosition = progressBarPosition === ProgressBarPosition.BOTTOM; return ( - + <> + updateSetting('progressBarPosition', position)} + valueToDisplayData={VALUE_TO_DISPLAY_DATA} + /> + {supportsAutoVerticalPosition && ( + updateSetting('progressBarPositionAutoVertical', position)} + valueToDisplayData={VALUE_TO_DISPLAY_DATA_AUTO_VERTICAL} + /> + )} + ); }; diff --git a/src/modules/reader/constants/ReaderSettings.constants.tsx b/src/modules/reader/constants/ReaderSettings.constants.tsx index 3891eb4c..72523b5d 100644 --- a/src/modules/reader/constants/ReaderSettings.constants.tsx +++ b/src/modules/reader/constants/ReaderSettings.constants.tsx @@ -50,6 +50,7 @@ const GLOBAL_READER_SETTING_OBJECT: Record