Improve reader horizontal mode scroll Y to X re-mapping
When scrolling really fast, the delta value could increase, which leads to incorrect trackpad detection, because the delta value is not consistent over consecutive scroll events
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
import { MutableRefObject, useEffect } from 'react';
|
||||
import { ReadingDirection, ReadingMode } from '@/features/reader/Reader.types.ts';
|
||||
import { PointerDeviceUtil } from '@/lib/PointerDeviceUtil.ts';
|
||||
|
||||
export const useReaderHorizontalModeInvertXYScrolling = (
|
||||
readingMode: ReadingMode,
|
||||
@@ -16,60 +17,45 @@ export const useReaderHorizontalModeInvertXYScrolling = (
|
||||
) => {
|
||||
// invert x and y scrolling for the continuous horizontal reading mode
|
||||
useEffect(() => {
|
||||
const scrollElement = scrollElementRef.current;
|
||||
|
||||
if (readingMode !== ReadingMode.CONTINUOUS_HORIZONTAL) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
if (!scrollElementRef.current) {
|
||||
if (!scrollElement) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
let previousDeltaX: number | undefined;
|
||||
let previousDeltaY: number | undefined;
|
||||
|
||||
// Trackpads can be identified by checking the delta values.
|
||||
// For a trackpad these values are not consistent since it basically behaves like scrolling via touch.
|
||||
// While for a mouse the values should always have the same value because each wheel turn scrolls the same exact amount.
|
||||
let isTrackpad: boolean | undefined;
|
||||
|
||||
const handleScroll = (e: WheelEvent) => {
|
||||
// Trackpads can scroll horizontally without the need of having "shift" pressed.
|
||||
// This is a problem because the hook will consider this to be a vertical scroll event and will invert it, which
|
||||
// breaks scrolling horizontally on trackpads.
|
||||
if (isTrackpad === true) {
|
||||
const isHorizontalScroll = Math.abs(e.deltaX) > Math.abs(e.deltaY);
|
||||
if (isHorizontalScroll) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trackpads can scroll horizontally without having shift pressed down.
|
||||
// This makes mapping vertical scrolling to horizontal scrolling unnecessary, and additionally, it feels weird and unexpected.
|
||||
// Especially since pages can cause vertical overflow which requires scrolling up and down.
|
||||
const isTrackPadLike = PointerDeviceUtil.isTrackPadLike();
|
||||
if (isTrackPadLike) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const isConsistentDeltaX = !Math.abs(Math.abs(previousDeltaX ?? e.deltaX) - Math.abs(e.deltaX));
|
||||
const isConsistentDeltaY = !Math.abs(Math.abs(previousDeltaY ?? e.deltaY) - Math.abs(e.deltaY));
|
||||
|
||||
previousDeltaX = e.deltaX;
|
||||
previousDeltaY = e.deltaY;
|
||||
|
||||
if (!isTrackpad) {
|
||||
isTrackpad = !isConsistentDeltaX || !isConsistentDeltaY;
|
||||
}
|
||||
|
||||
const preventInversion = isTrackpad === undefined;
|
||||
if (preventInversion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.shiftKey) {
|
||||
scrollElementRef.current?.scrollBy({
|
||||
scrollElement.scrollBy({
|
||||
top: e.deltaY,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
scrollElementRef.current?.scrollBy({
|
||||
scrollElement.scrollBy({
|
||||
left: readingDirection === ReadingDirection.LTR ? e.deltaY : e.deltaY * -1,
|
||||
});
|
||||
};
|
||||
|
||||
scrollElementRef.current.addEventListener('wheel', handleScroll);
|
||||
return () => scrollElementRef.current?.removeEventListener('wheel', handleScroll);
|
||||
scrollElement.addEventListener('wheel', handleScroll);
|
||||
return () => scrollElement.removeEventListener('wheel', handleScroll);
|
||||
}, [readingMode, readingDirection]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user