Prevent scroll on swipe and drag gestures

This commit is contained in:
Alexander Zinchuk 2021-08-21 13:33:11 +03:00
parent 69acc87529
commit 1450fa4631
8 changed files with 58 additions and 20 deletions

View File

@ -110,12 +110,17 @@ const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return captureEvents(element, { return captureEvents(element, {
selectorToPreventScroll: '.Profile, .settings-content',
onSwipe: IS_TOUCH_ENV ? (e, direction) => { onSwipe: IS_TOUCH_ENV ? (e, direction) => {
if (direction === SwipeDirection.Right) { if (direction === SwipeDirection.Right) {
selectPreviousMedia(); selectPreviousMedia();
return true;
} else if (direction === SwipeDirection.Left) { } else if (direction === SwipeDirection.Left) {
selectNextMedia(); selectNextMedia();
return true;
} }
return false;
} : undefined, } : undefined,
}); });
}, [selectNextMedia, selectPreviousMedia]); }, [selectNextMedia, selectPreviousMedia]);

View File

@ -137,12 +137,17 @@ const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return captureEvents(transitionRef.current, { return captureEvents(transitionRef.current, {
selectorToPreventScroll: '.Profile',
onSwipe: ((e, direction) => { onSwipe: ((e, direction) => {
if (direction === SwipeDirection.Left) { if (direction === SwipeDirection.Left) {
setActiveChatFolder(Math.min(activeChatFolder + 1, folderTabs.length - 1)); setActiveChatFolder(Math.min(activeChatFolder + 1, folderTabs.length - 1));
return true;
} else if (direction === SwipeDirection.Right) { } else if (direction === SwipeDirection.Right) {
setActiveChatFolder(Math.max(0, activeChatFolder - 1)); setActiveChatFolder(Math.max(0, activeChatFolder - 1));
return true;
} }
return false;
}), }),
}); });
}, [activeChatFolder, folderTabs, setActiveChatFolder]); }, [activeChatFolder, folderTabs, setActiveChatFolder]);

View File

@ -10,7 +10,6 @@
.color-picker { .color-picker {
margin-top: 1rem; margin-top: 1rem;
height: 12rem; height: 12rem;
touch-action: none;
} }
.hue-picker { .hue-picker {

View File

@ -109,6 +109,8 @@ 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!, {
@ -116,6 +118,7 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
onDrag: handleColorDrag, onDrag: handleColorDrag,
onRelease: unmarkIsDragging, onRelease: unmarkIsDragging,
onClick: unmarkIsDragging, onClick: unmarkIsDragging,
selectorToPreventScroll: '.SettingsGeneralBackgroundColor',
withCursor: true, withCursor: true,
}); });
@ -125,6 +128,8 @@ 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!, {
@ -132,6 +137,7 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
onDrag: handleHueDrag, onDrag: handleHueDrag,
onRelease: unmarkIsDragging, onRelease: unmarkIsDragging,
onClick: unmarkIsDragging, onClick: unmarkIsDragging,
selectorToPreventScroll: '.SettingsGeneralBackgroundColor',
withCursor: true, withCursor: true,
}); });
}, [markIsDragging, unmarkIsDragging]); }, [markIsDragging, unmarkIsDragging]);

View File

@ -75,6 +75,7 @@ export default function useOuterHandlers(
let startedAt: number | undefined; let startedAt: number | undefined;
return captureEvents(containerRef.current!, { return captureEvents(containerRef.current!, {
selectorToPreventScroll: '.MessageList',
onSwipe: ((e, direction) => { onSwipe: ((e, direction) => {
if (direction === SwipeDirection.Left) { if (direction === SwipeDirection.Left) {
if (!startedAt) { if (!startedAt) {
@ -82,11 +83,15 @@ export default function useOuterHandlers(
} }
markSwiped(); markSwiped();
return true;
} else if (direction === SwipeDirection.Right) { } else if (direction === SwipeDirection.Right) {
startedAt = undefined; startedAt = undefined;
unmarkSwiped(); unmarkSwiped();
} }
return false;
}), }),
onRelease: () => { onRelease: () => {
if (!startedAt) { if (!startedAt) {

View File

@ -5,11 +5,6 @@
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
@supports (overflow-y: overlay) {
overflow-y: overlay !important;
}
> .profile-info > .ChatInfo { > .profile-info > .ChatInfo {
grid-area: chat_info; grid-area: chat_info;

View File

@ -211,12 +211,17 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
} }
return captureEvents(transitionRef.current, { return captureEvents(transitionRef.current, {
selectorToPreventScroll: '.Profile',
onSwipe: ((e, direction) => { onSwipe: ((e, direction) => {
if (direction === SwipeDirection.Left) { if (direction === SwipeDirection.Left) {
setActiveTab(Math.min(activeTab + 1, tabs.length - 1)); setActiveTab(Math.min(activeTab + 1, tabs.length - 1));
return true;
} else if (direction === SwipeDirection.Right) { } else if (direction === SwipeDirection.Right) {
setActiveTab(Math.max(0, activeTab - 1)); setActiveTab(Math.max(0, activeTab - 1));
return true;
} }
return false;
}), }),
}); });
}, [activeTab, tabs.length]); }, [activeTab, tabs.length]);

View File

@ -1,4 +1,4 @@
import { IS_IOS } from './environment'; import { IS_IOS, IS_TOUCH_ENV } from './environment';
export enum SwipeDirection { export enum SwipeDirection {
Up, Up,
@ -17,10 +17,11 @@ interface CaptureOptions {
dragOffsetX: number; dragOffsetX: number;
dragOffsetY: number; dragOffsetY: number;
}, },
) => void; ) => boolean | void;
onSwipe?: (e: Event, direction: SwipeDirection) => void; onSwipe?: (e: Event, direction: SwipeDirection) => boolean | void;
onClick?: (e: MouseEvent | TouchEvent) => void; onClick?: (e: MouseEvent | TouchEvent) => void;
excludedClosestSelector?: string; excludedClosestSelector?: string;
selectorToPreventScroll?: string;
withCursor?: boolean; withCursor?: boolean;
} }
@ -100,6 +101,12 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
captureEvent = undefined; captureEvent = undefined;
if (hasMoved) { if (hasMoved) {
if (IS_TOUCH_ENV && options.selectorToPreventScroll) {
Array.from(document.querySelectorAll<HTMLElement>(options.selectorToPreventScroll)).forEach((scrollable) => {
scrollable.style.overflow = '';
});
}
if (options.onRelease) { if (options.onRelease) {
options.onRelease(e); options.onRelease(e);
} }
@ -131,13 +138,22 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
hasMoved = true; hasMoved = true;
} }
let shouldPreventScroll: boolean | void;
if (options.onDrag) { if (options.onDrag) {
e.preventDefault(); shouldPreventScroll = options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY });
options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY });
} }
if (options.onSwipe) { if (options.onSwipe) {
onSwipe(e, dragOffsetX, dragOffsetY); shouldPreventScroll = onSwipe(e, dragOffsetX, dragOffsetY);
}
if (IS_TOUCH_ENV && shouldPreventScroll && options.selectorToPreventScroll) {
if (options.selectorToPreventScroll) {
Array.from(document.querySelectorAll<HTMLElement>(options.selectorToPreventScroll)).forEach((scrollable) => {
scrollable.style.overflow = 'hidden';
});
}
} }
} }
} }
@ -147,7 +163,7 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
if (IS_IOS) { if (IS_IOS) {
const x = (e as RealTouchEvent).touches[0].pageX; const x = (e as RealTouchEvent).touches[0].pageX;
if (x <= IOS_SCREEN_EDGE_THRESHOLD || x >= window.innerWidth - IOS_SCREEN_EDGE_THRESHOLD) { if (x <= IOS_SCREEN_EDGE_THRESHOLD || x >= window.innerWidth - IOS_SCREEN_EDGE_THRESHOLD) {
return; return undefined;
} }
} }
@ -159,7 +175,7 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
const ratio = Math.max(xAbs, yAbs) / Math.min(xAbs, yAbs); const ratio = Math.max(xAbs, yAbs) / Math.min(xAbs, yAbs);
// Diagonal swipe // Diagonal swipe
if (ratio < 2) { if (ratio < 2) {
return; return undefined;
} }
} }
@ -170,7 +186,7 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) {
} }
} }
processSwipe(e, currentSwipeAxis, dragOffsetX, dragOffsetY, options.onSwipe!); return processSwipe(e, currentSwipeAxis, dragOffsetX, dragOffsetY, options.onSwipe!);
} }
element.addEventListener('mousedown', onCapture); element.addEventListener('mousedown', onCapture);
@ -187,19 +203,21 @@ function processSwipe(
currentSwipeAxis: TSwipeAxis, currentSwipeAxis: TSwipeAxis,
dragOffsetX: number, dragOffsetX: number,
dragOffsetY: number, dragOffsetY: number,
onSwipe: (e: Event, direction: SwipeDirection) => void, onSwipe: (e: Event, direction: SwipeDirection) => boolean | void,
) { ) {
if (currentSwipeAxis === 'x') { if (currentSwipeAxis === 'x') {
if (dragOffsetX < 0) { if (dragOffsetX < 0) {
onSwipe(e, SwipeDirection.Left); return onSwipe(e, SwipeDirection.Left);
} else { } else {
onSwipe(e, SwipeDirection.Right); return onSwipe(e, SwipeDirection.Right);
} }
} else if (currentSwipeAxis === 'y') { } else if (currentSwipeAxis === 'y') {
if (dragOffsetY < 0) { if (dragOffsetY < 0) {
onSwipe(e, SwipeDirection.Up); return onSwipe(e, SwipeDirection.Up);
} else { } else {
onSwipe(e, SwipeDirection.Down); return onSwipe(e, SwipeDirection.Down);
} }
} }
return undefined;
} }