Improve "MobileReaderProgressBar" progress bar click/drag handling
Convert clicks on the progress bar in such a way, that there is a "padding" around the page "dots". Thus, e.g. even if the click was actually for page 1, if it is inside page 2 padding, it will behave like it was a click for page 2
This commit is contained in:
@@ -47,6 +47,7 @@ const BaseReaderProgressBar = ({
|
|||||||
setIsDragging,
|
setIsDragging,
|
||||||
openPage,
|
openPage,
|
||||||
direction,
|
direction,
|
||||||
|
fullSegmentClicks,
|
||||||
}: ReaderProgressBarProps &
|
}: ReaderProgressBarProps &
|
||||||
Pick<TReaderProgressBarContext, 'isDragging' | 'setIsDragging'> &
|
Pick<TReaderProgressBarContext, 'isDragging' | 'setIsDragging'> &
|
||||||
Pick<ComponentProps<typeof ReaderProgressBarSlotWrapper>, 'createProgressBarSlot'> & {
|
Pick<ComponentProps<typeof ReaderProgressBarSlotWrapper>, 'createProgressBarSlot'> & {
|
||||||
@@ -69,6 +70,7 @@ const BaseReaderProgressBar = ({
|
|||||||
};
|
};
|
||||||
openPage: ReturnType<typeof ReaderControls.useOpenPage>;
|
openPage: ReturnType<typeof ReaderControls.useOpenPage>;
|
||||||
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
direction: ReturnType<typeof ReaderService.useGetThemeDirection>;
|
||||||
|
fullSegmentClicks: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const progressBarRef = useRef<HTMLDivElement | null>(null);
|
const progressBarRef = useRef<HTMLDivElement | null>(null);
|
||||||
const draggingDetectionTimeout = useRef<NodeJS.Timeout>();
|
const draggingDetectionTimeout = useRef<NodeJS.Timeout>();
|
||||||
@@ -107,6 +109,7 @@ const BaseReaderProgressBar = ({
|
|||||||
pages,
|
pages,
|
||||||
progressBarPosition,
|
progressBarPosition,
|
||||||
getOptionForDirection,
|
getOptionForDirection,
|
||||||
|
fullSegmentClicks,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMouseDown = (e: React.MouseEvent | React.TouchEvent) => {
|
const handleMouseDown = (e: React.MouseEvent | React.TouchEvent) => {
|
||||||
@@ -123,6 +126,7 @@ const BaseReaderProgressBar = ({
|
|||||||
progressBarRef.current.getBoundingClientRect(),
|
progressBarRef.current.getBoundingClientRect(),
|
||||||
pages,
|
pages,
|
||||||
isHorizontalPosition,
|
isHorizontalPosition,
|
||||||
|
fullSegmentClicks,
|
||||||
getOptionForDirection,
|
getOptionForDirection,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ const BaseMobileReaderProgressBar = ({
|
|||||||
{getOptionForDirection(<SkipPreviousIcon />, <SkipNextIcon />, direction)}
|
{getOptionForDirection(<SkipPreviousIcon />, <SkipNextIcon />, direction)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<ReaderProgressBar
|
<ReaderProgressBar
|
||||||
|
fullSegmentClicks={false}
|
||||||
createProgressBarSlot={useCallback(
|
createProgressBarSlot={useCallback(
|
||||||
(page, pagesIndex, _2, _3, _4, _5, isTrailingPage, totalPages) => (
|
(page, pagesIndex, _2, _3, _4, _5, isTrailingPage, totalPages) => (
|
||||||
<ReaderProgressBarSlotMobile
|
<ReaderProgressBarSlotMobile
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const BaseStandardReaderProgressBar = ({
|
|||||||
return (
|
return (
|
||||||
<ReaderProgressBarDirectionWrapper>
|
<ReaderProgressBarDirectionWrapper>
|
||||||
<ReaderProgressBar
|
<ReaderProgressBar
|
||||||
|
fullSegmentClicks
|
||||||
createProgressBarSlot={useCallback(
|
createProgressBarSlot={useCallback(
|
||||||
(
|
(
|
||||||
page,
|
page,
|
||||||
|
|||||||
@@ -543,6 +543,7 @@ export class ReaderControls {
|
|||||||
pages: ReaderProgressBarProps['pages'],
|
pages: ReaderProgressBarProps['pages'],
|
||||||
progressBarPosition: ProgressBarPosition,
|
progressBarPosition: ProgressBarPosition,
|
||||||
getOptionForDirectionFn: typeof getOptionForDirection,
|
getOptionForDirectionFn: typeof getOptionForDirection,
|
||||||
|
fullSegmentClicks: boolean,
|
||||||
): void {
|
): void {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isDragging) {
|
if (!isDragging) {
|
||||||
@@ -562,6 +563,7 @@ export class ReaderControls {
|
|||||||
progressBarRef.current.getBoundingClientRect(),
|
progressBarRef.current.getBoundingClientRect(),
|
||||||
pages,
|
pages,
|
||||||
isHorizontal,
|
isHorizontal,
|
||||||
|
fullSegmentClicks,
|
||||||
getOptionForDirectionFn,
|
getOptionForDirectionFn,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,17 +48,26 @@ export const getPageForMousePos = (
|
|||||||
elementRect: DOMRect,
|
elementRect: DOMRect,
|
||||||
pages: ReaderProgressBarProps['pages'],
|
pages: ReaderProgressBarProps['pages'],
|
||||||
isHorizontalPosition: boolean,
|
isHorizontalPosition: boolean,
|
||||||
|
fullSegmentClicks: boolean,
|
||||||
getOptionForDirection: typeof getOptionForDirectionImpl,
|
getOptionForDirection: typeof getOptionForDirectionImpl,
|
||||||
): ReaderProgressBarProps['pages'][number] => {
|
): ReaderProgressBarProps['pages'][number] => {
|
||||||
const pos = isHorizontalPosition ? coordinates.clientX : coordinates.clientY;
|
const pos = isHorizontalPosition ? coordinates.clientX : coordinates.clientY;
|
||||||
const rectPos = isHorizontalPosition ? elementRect.left : elementRect.top;
|
const rectPos = isHorizontalPosition ? elementRect.left : elementRect.top;
|
||||||
const rectSize = isHorizontalPosition ? elementRect.width : elementRect.height;
|
const rectSize = isHorizontalPosition ? elementRect.width : elementRect.height;
|
||||||
|
|
||||||
const mouseXPosRelativeToProgressBar = pos - rectPos;
|
const mousePosRelativeToProgressBar = pos - rectPos;
|
||||||
const pageForMouseXPos = Math.ceil((mouseXPosRelativeToProgressBar / rectSize) * pages.length);
|
|
||||||
const minPage = Math.max(1, pageForMouseXPos);
|
const totalPages = pages.length - Number(!fullSegmentClicks);
|
||||||
const maxPage = Math.min(minPage, pages.length);
|
|
||||||
const newPageIndex = getOptionForDirection(maxPage - 1, pages.length - maxPage);
|
const segmentWidth = rectSize / totalPages;
|
||||||
|
const clickedSegmentIndex = Math.floor(mousePosRelativeToProgressBar / segmentWidth);
|
||||||
|
const segmentMiddlePoint = (clickedSegmentIndex + (fullSegmentClicks ? 1 : 0.5)) * segmentWidth;
|
||||||
|
const actualClickedSegmentIndex =
|
||||||
|
mousePosRelativeToProgressBar <= segmentMiddlePoint ? clickedSegmentIndex : clickedSegmentIndex + 1;
|
||||||
|
|
||||||
|
const minPageIndex = Math.max(0, actualClickedSegmentIndex);
|
||||||
|
const maxPageIndex = Math.min(minPageIndex, pages.length - 1);
|
||||||
|
const newPageIndex = getOptionForDirection(maxPageIndex, pages.length - 1 - maxPageIndex);
|
||||||
|
|
||||||
return pages[newPageIndex];
|
return pages[newPageIndex];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user