Various fixes for drag and swipe gestures

This commit is contained in:
Alexander Zinchuk 2021-08-21 13:33:21 +03:00
parent 62c0c735ea
commit 97479b4af6
3 changed files with 28 additions and 28 deletions

View File

@ -109,8 +109,6 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!)); setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));
markIsDragging(); markIsDragging();
return true;
} }
captureEvents(colorPickerRef.current!, { captureEvents(colorPickerRef.current!, {
@ -128,8 +126,6 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!)); setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));
markIsDragging(); markIsDragging();
return true;
} }
captureEvents(huePickerRef.current!, { captureEvents(huePickerRef.current!, {

View File

@ -428,6 +428,8 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
} else if (!(e.target && (e.target as HTMLElement).closest('.MediaViewerFooter'))) { } else if (!(e.target && (e.target as HTMLElement).closest('.MediaViewerFooter'))) {
close(); close();
} }
return true;
} : undefined, } : undefined,
}); });
}, [close, isFooterHidden, isGif, isPhoto, isZoomed, selectNextMedia, selectPreviousMedia]); }, [close, isFooterHidden, isGif, isPhoto, isZoomed, selectNextMedia, selectPreviousMedia]);

View File

@ -17,8 +17,8 @@ interface CaptureOptions {
dragOffsetX: number; dragOffsetX: number;
dragOffsetY: number; dragOffsetY: number;
}, },
) => boolean | void; ) => void;
onSwipe?: (e: Event, direction: SwipeDirection) => boolean | void; onSwipe?: (e: Event, direction: SwipeDirection) => boolean;
onClick?: (e: MouseEvent | TouchEvent) => void; onClick?: (e: MouseEvent | TouchEvent) => void;
excludedClosestSelector?: string; excludedClosestSelector?: string;
selectorToPreventScroll?: string; selectorToPreventScroll?: string;
@ -60,9 +60,12 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
document.addEventListener('mousemove', onMove); document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onRelease); document.addEventListener('mouseup', onRelease);
} else if (e.type === 'touchstart') { } else if (e.type === 'touchstart') {
document.addEventListener('touchmove', onMove); // We need to always listen on `touchstart` target:
document.addEventListener('touchend', onRelease); // https://stackoverflow.com/questions/33298828/touch-move-event-dont-fire-after-touch-start-target-is-removed
document.addEventListener('touchcancel', onRelease); const target = e.target as HTMLElement;
target.addEventListener('touchmove', onMove);
target.addEventListener('touchend', onRelease);
target.addEventListener('touchcancel', onRelease);
if ('touches' in e) { if ('touches' in e) {
if (e.pageX === undefined) { if (e.pageX === undefined) {
@ -94,19 +97,19 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
document.removeEventListener('mouseup', onRelease); document.removeEventListener('mouseup', onRelease);
document.removeEventListener('mousemove', onMove); document.removeEventListener('mousemove', onMove);
document.removeEventListener('touchcancel', onRelease); (captureEvent.target as HTMLElement).removeEventListener('touchcancel', onRelease);
document.removeEventListener('touchend', onRelease); (captureEvent.target as HTMLElement).removeEventListener('touchend', onRelease);
document.removeEventListener('touchmove', onMove); (captureEvent.target as HTMLElement).removeEventListener('touchmove', onMove);
captureEvent = undefined; captureEvent = undefined;
if (hasMoved) { if (options.selectorToPreventScroll) {
if (IS_TOUCH_ENV && options.selectorToPreventScroll) { Array.from(document.querySelectorAll<HTMLElement>(options.selectorToPreventScroll)).forEach((scrollable) => {
Array.from(document.querySelectorAll<HTMLElement>(options.selectorToPreventScroll)).forEach((scrollable) => { scrollable.style.overflow = '';
scrollable.style.overflow = ''; });
}); }
}
if (hasMoved) {
if (options.onRelease) { if (options.onRelease) {
options.onRelease(e); options.onRelease(e);
} }
@ -138,10 +141,11 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
hasMoved = true; hasMoved = true;
} }
let shouldPreventScroll: boolean | void; let shouldPreventScroll = false;
if (options.onDrag) { if (options.onDrag) {
shouldPreventScroll = options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY }); options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY });
shouldPreventScroll = true;
} }
if (options.onSwipe && !hasSwiped) { if (options.onSwipe && !hasSwiped) {
@ -207,23 +211,21 @@ function processSwipe(
currentSwipeAxis: TSwipeAxis, currentSwipeAxis: TSwipeAxis,
dragOffsetX: number, dragOffsetX: number,
dragOffsetY: number, dragOffsetY: number,
onSwipe: (e: Event, direction: SwipeDirection) => boolean | void, onSwipe: (e: Event, direction: SwipeDirection) => boolean,
) { ) {
let isSwiped: boolean | void = false;
if (currentSwipeAxis === 'x') { if (currentSwipeAxis === 'x') {
if (dragOffsetX < 0) { if (dragOffsetX < 0) {
isSwiped = onSwipe(e, SwipeDirection.Left); return onSwipe(e, SwipeDirection.Left);
} else { } else {
isSwiped = onSwipe(e, SwipeDirection.Right); return onSwipe(e, SwipeDirection.Right);
} }
} else if (currentSwipeAxis === 'y') { } else if (currentSwipeAxis === 'y') {
if (dragOffsetY < 0) { if (dragOffsetY < 0) {
isSwiped = onSwipe(e, SwipeDirection.Up); return onSwipe(e, SwipeDirection.Up);
} else { } else {
isSwiped = onSwipe(e, SwipeDirection.Down); return onSwipe(e, SwipeDirection.Down);
} }
} }
return isSwiped === undefined ? true : isSwiped; return false;
} }