From 1450fa46311d03b4385cf7a4739a2408288acd00 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Sat, 21 Aug 2021 13:33:11 +0300 Subject: [PATCH] Prevent scroll on swipe and drag gestures --- src/components/common/ProfileInfo.tsx | 5 ++ src/components/left/main/ChatFolders.tsx | 5 ++ .../SettingsGeneralBackgroundColor.scss | 1 - .../SettingsGeneralBackgroundColor.tsx | 6 +++ .../middle/message/hooks/useOuterHandlers.ts | 5 ++ src/components/right/Profile.scss | 5 -- src/components/right/Profile.tsx | 5 ++ src/util/captureEvents.ts | 46 +++++++++++++------ 8 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/components/common/ProfileInfo.tsx b/src/components/common/ProfileInfo.tsx index 6127b5f3..a8133c76 100644 --- a/src/components/common/ProfileInfo.tsx +++ b/src/components/common/ProfileInfo.tsx @@ -110,12 +110,17 @@ const ProfileInfo: FC = ({ } return captureEvents(element, { + selectorToPreventScroll: '.Profile, .settings-content', onSwipe: IS_TOUCH_ENV ? (e, direction) => { if (direction === SwipeDirection.Right) { selectPreviousMedia(); + return true; } else if (direction === SwipeDirection.Left) { selectNextMedia(); + return true; } + + return false; } : undefined, }); }, [selectNextMedia, selectPreviousMedia]); diff --git a/src/components/left/main/ChatFolders.tsx b/src/components/left/main/ChatFolders.tsx index 3fcf4dd2..05828a8a 100644 --- a/src/components/left/main/ChatFolders.tsx +++ b/src/components/left/main/ChatFolders.tsx @@ -137,12 +137,17 @@ const ChatFolders: FC = ({ } return captureEvents(transitionRef.current, { + selectorToPreventScroll: '.Profile', onSwipe: ((e, direction) => { if (direction === SwipeDirection.Left) { setActiveChatFolder(Math.min(activeChatFolder + 1, folderTabs.length - 1)); + return true; } else if (direction === SwipeDirection.Right) { setActiveChatFolder(Math.max(0, activeChatFolder - 1)); + return true; } + + return false; }), }); }, [activeChatFolder, folderTabs, setActiveChatFolder]); diff --git a/src/components/left/settings/SettingsGeneralBackgroundColor.scss b/src/components/left/settings/SettingsGeneralBackgroundColor.scss index 6c05e8b0..7e90f37f 100644 --- a/src/components/left/settings/SettingsGeneralBackgroundColor.scss +++ b/src/components/left/settings/SettingsGeneralBackgroundColor.scss @@ -10,7 +10,6 @@ .color-picker { margin-top: 1rem; height: 12rem; - touch-action: none; } .hue-picker { diff --git a/src/components/left/settings/SettingsGeneralBackgroundColor.tsx b/src/components/left/settings/SettingsGeneralBackgroundColor.tsx index f900283b..0add0584 100644 --- a/src/components/left/settings/SettingsGeneralBackgroundColor.tsx +++ b/src/components/left/settings/SettingsGeneralBackgroundColor.tsx @@ -109,6 +109,8 @@ const SettingsGeneralBackground: FC = ({ setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!)); markIsDragging(); + + return true; } captureEvents(colorPickerRef.current!, { @@ -116,6 +118,7 @@ const SettingsGeneralBackground: FC = ({ onDrag: handleColorDrag, onRelease: unmarkIsDragging, onClick: unmarkIsDragging, + selectorToPreventScroll: '.SettingsGeneralBackgroundColor', withCursor: true, }); @@ -125,6 +128,8 @@ const SettingsGeneralBackground: FC = ({ setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!)); markIsDragging(); + + return true; } captureEvents(huePickerRef.current!, { @@ -132,6 +137,7 @@ const SettingsGeneralBackground: FC = ({ onDrag: handleHueDrag, onRelease: unmarkIsDragging, onClick: unmarkIsDragging, + selectorToPreventScroll: '.SettingsGeneralBackgroundColor', withCursor: true, }); }, [markIsDragging, unmarkIsDragging]); diff --git a/src/components/middle/message/hooks/useOuterHandlers.ts b/src/components/middle/message/hooks/useOuterHandlers.ts index f03ffa0e..69753338 100644 --- a/src/components/middle/message/hooks/useOuterHandlers.ts +++ b/src/components/middle/message/hooks/useOuterHandlers.ts @@ -75,6 +75,7 @@ export default function useOuterHandlers( let startedAt: number | undefined; return captureEvents(containerRef.current!, { + selectorToPreventScroll: '.MessageList', onSwipe: ((e, direction) => { if (direction === SwipeDirection.Left) { if (!startedAt) { @@ -82,11 +83,15 @@ export default function useOuterHandlers( } markSwiped(); + + return true; } else if (direction === SwipeDirection.Right) { startedAt = undefined; unmarkSwiped(); } + + return false; }), onRelease: () => { if (!startedAt) { diff --git a/src/components/right/Profile.scss b/src/components/right/Profile.scss index 9150e28c..c3cbf4d5 100644 --- a/src/components/right/Profile.scss +++ b/src/components/right/Profile.scss @@ -5,11 +5,6 @@ overflow-y: scroll; overflow-x: hidden; - @supports (overflow-y: overlay) { - overflow-y: overlay !important; - } - - > .profile-info > .ChatInfo { grid-area: chat_info; diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index 19c34b83..6bd6ed31 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -211,12 +211,17 @@ const Profile: FC = ({ } return captureEvents(transitionRef.current, { + selectorToPreventScroll: '.Profile', onSwipe: ((e, direction) => { if (direction === SwipeDirection.Left) { setActiveTab(Math.min(activeTab + 1, tabs.length - 1)); + return true; } else if (direction === SwipeDirection.Right) { setActiveTab(Math.max(0, activeTab - 1)); + return true; } + + return false; }), }); }, [activeTab, tabs.length]); diff --git a/src/util/captureEvents.ts b/src/util/captureEvents.ts index 2614be10..40ef0537 100644 --- a/src/util/captureEvents.ts +++ b/src/util/captureEvents.ts @@ -1,4 +1,4 @@ -import { IS_IOS } from './environment'; +import { IS_IOS, IS_TOUCH_ENV } from './environment'; export enum SwipeDirection { Up, @@ -17,10 +17,11 @@ interface CaptureOptions { dragOffsetX: number; dragOffsetY: number; }, - ) => void; - onSwipe?: (e: Event, direction: SwipeDirection) => void; + ) => boolean | void; + onSwipe?: (e: Event, direction: SwipeDirection) => boolean | void; onClick?: (e: MouseEvent | TouchEvent) => void; excludedClosestSelector?: string; + selectorToPreventScroll?: string; withCursor?: boolean; } @@ -100,6 +101,12 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) { captureEvent = undefined; if (hasMoved) { + if (IS_TOUCH_ENV && options.selectorToPreventScroll) { + Array.from(document.querySelectorAll(options.selectorToPreventScroll)).forEach((scrollable) => { + scrollable.style.overflow = ''; + }); + } + if (options.onRelease) { options.onRelease(e); } @@ -131,13 +138,22 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) { hasMoved = true; } + let shouldPreventScroll: boolean | void; + if (options.onDrag) { - e.preventDefault(); - options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY }); + shouldPreventScroll = options.onDrag(e, captureEvent, { dragOffsetX, dragOffsetY }); } 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(options.selectorToPreventScroll)).forEach((scrollable) => { + scrollable.style.overflow = 'hidden'; + }); + } } } } @@ -147,7 +163,7 @@ export function captureEvents(element: HTMLElement, options: CaptureOptions) { if (IS_IOS) { const x = (e as RealTouchEvent).touches[0].pageX; 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); // Diagonal swipe 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); @@ -187,19 +203,21 @@ function processSwipe( currentSwipeAxis: TSwipeAxis, dragOffsetX: number, dragOffsetY: number, - onSwipe: (e: Event, direction: SwipeDirection) => void, + onSwipe: (e: Event, direction: SwipeDirection) => boolean | void, ) { if (currentSwipeAxis === 'x') { if (dragOffsetX < 0) { - onSwipe(e, SwipeDirection.Left); + return onSwipe(e, SwipeDirection.Left); } else { - onSwipe(e, SwipeDirection.Right); + return onSwipe(e, SwipeDirection.Right); } } else if (currentSwipeAxis === 'y') { if (dragOffsetY < 0) { - onSwipe(e, SwipeDirection.Up); + return onSwipe(e, SwipeDirection.Up); } else { - onSwipe(e, SwipeDirection.Down); + return onSwipe(e, SwipeDirection.Down); } } + + return undefined; }