Fix drawer swipe (#7007)
* Fix drawer swipe * Remove existing setDrawerSwipeDisabled management This is already pretty error-prone. And with tracking whether we're idle it's going to get more complicated. Let's pause and think. * Move setDrawerSwipeDisabled logic into Pager * Remove win/2 threshold It feels super arbitrary and breaks muscle memory. If the gesture is reliable, we shouldn't need it. * Maybe work around iOS freeze * Tweak gestures, add comments * Tune gestures
This commit is contained in:
@@ -0,0 +1,876 @@
|
|||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/commonjs/index.js b/node_modules/react-native-drawer-layout/lib/commonjs/index.js
|
||||||
|
index 3dce76e..6c4b3e5 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/commonjs/index.js
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/commonjs/index.js
|
||||||
|
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "Drawer", {
|
||||||
|
return _Drawer.Drawer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
+Object.defineProperty(exports, "DrawerGestureContext", {
|
||||||
|
+ enumerable: true,
|
||||||
|
+ get: function () {
|
||||||
|
+ return _DrawerGestureContext.DrawerGestureContext;
|
||||||
|
+ }
|
||||||
|
+});
|
||||||
|
Object.defineProperty(exports, "DrawerProgressContext", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
@@ -21,6 +27,7 @@ Object.defineProperty(exports, "useDrawerProgress", {
|
||||||
|
return _useDrawerProgress.useDrawerProgress;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
+var _DrawerGestureContext = require("./utils/DrawerGestureContext.js");
|
||||||
|
var _DrawerProgressContext = require("./utils/DrawerProgressContext.js");
|
||||||
|
var _useDrawerProgress = require("./utils/useDrawerProgress.js");
|
||||||
|
var _Drawer = require("./views/Drawer");
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/commonjs/utils/DrawerGestureContext.js b/node_modules/react-native-drawer-layout/lib/commonjs/utils/DrawerGestureContext.js
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..de6d793
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/commonjs/utils/DrawerGestureContext.js
|
||||||
|
@@ -0,0 +1,11 @@
|
||||||
|
+"use strict";
|
||||||
|
+
|
||||||
|
+Object.defineProperty(exports, "__esModule", {
|
||||||
|
+ value: true
|
||||||
|
+});
|
||||||
|
+exports.DrawerGestureContext = void 0;
|
||||||
|
+var React = _interopRequireWildcard(require("react"));
|
||||||
|
+function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||||
|
+function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||||
|
+const DrawerGestureContext = exports.DrawerGestureContext = /*#__PURE__*/React.createContext(undefined);
|
||||||
|
+//# sourceMappingURL=DrawerGestureContext.js.map
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/commonjs/views/Drawer.native.js b/node_modules/react-native-drawer-layout/lib/commonjs/views/Drawer.native.js
|
||||||
|
index fd65ab8..86a9a6a 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/commonjs/views/Drawer.native.js
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/commonjs/views/Drawer.native.js
|
||||||
|
@@ -8,6 +8,7 @@ var React = _interopRequireWildcard(require("react"));
|
||||||
|
var _reactNative = require("react-native");
|
||||||
|
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
|
||||||
|
var _useLatestCallback = _interopRequireDefault(require("use-latest-callback"));
|
||||||
|
+var _DrawerGestureContext = require("../utils/DrawerGestureContext.js");
|
||||||
|
var _DrawerProgressContext = require("../utils/DrawerProgressContext.js");
|
||||||
|
var _getDrawerWidth = require("../utils/getDrawerWidth.js");
|
||||||
|
var _GestureHandler = require("./GestureHandler");
|
||||||
|
@@ -79,38 +80,38 @@ function Drawer({
|
||||||
|
return () => hideStatusBar(false);
|
||||||
|
}, [isOpen, hideStatusBarOnOpen, statusBarAnimation, hideStatusBar]);
|
||||||
|
const interactionHandleRef = React.useRef(null);
|
||||||
|
- const startInteraction = () => {
|
||||||
|
+ const startInteraction = React.useCallback(() => {
|
||||||
|
interactionHandleRef.current = _reactNative.InteractionManager.createInteractionHandle();
|
||||||
|
- };
|
||||||
|
- const endInteraction = () => {
|
||||||
|
+ }, []);
|
||||||
|
+ const endInteraction = React.useCallback(() => {
|
||||||
|
if (interactionHandleRef.current != null) {
|
||||||
|
_reactNative.InteractionManager.clearInteractionHandle(interactionHandleRef.current);
|
||||||
|
interactionHandleRef.current = null;
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
- const hideKeyboard = () => {
|
||||||
|
+ }, []);
|
||||||
|
+ const hideKeyboard = React.useCallback(() => {
|
||||||
|
if (keyboardDismissMode === 'on-drag') {
|
||||||
|
_reactNative.Keyboard.dismiss();
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
- const onGestureBegin = () => {
|
||||||
|
+ }, [keyboardDismissMode]);
|
||||||
|
+ const onGestureBegin = React.useCallback(() => {
|
||||||
|
onGestureStart?.();
|
||||||
|
startInteraction();
|
||||||
|
hideKeyboard();
|
||||||
|
hideStatusBar(true);
|
||||||
|
- };
|
||||||
|
- const onGestureFinish = () => {
|
||||||
|
+ }, [onGestureStart, startInteraction, hideKeyboard, hideStatusBar]);
|
||||||
|
+ const onGestureFinish = React.useCallback(() => {
|
||||||
|
onGestureEnd?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
- const onGestureAbort = () => {
|
||||||
|
+ }, [onGestureEnd, endInteraction]);
|
||||||
|
+ const onGestureAbort = React.useCallback(() => {
|
||||||
|
onGestureCancel?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
+ }, [onGestureCancel, endInteraction]);
|
||||||
|
|
||||||
|
// FIXME: Currently hitSlop is broken when on Android when drawer is on right
|
||||||
|
// https://github.com/software-mansion/react-native-gesture-handler/issues/569
|
||||||
|
- const hitSlop = isRight ?
|
||||||
|
+ const hitSlop = React.useMemo(() => isRight ?
|
||||||
|
// Extend hitSlop to the side of the screen when drawer is closed
|
||||||
|
// This lets the user drag the drawer from the side of the screen
|
||||||
|
{
|
||||||
|
@@ -119,7 +120,7 @@ function Drawer({
|
||||||
|
} : {
|
||||||
|
left: 0,
|
||||||
|
width: isOpen ? undefined : swipeEdgeWidth
|
||||||
|
- };
|
||||||
|
+ }, [isRight, isOpen, swipeEdgeWidth]);
|
||||||
|
const touchStartX = (0, _reactNativeReanimated.useSharedValue)(0);
|
||||||
|
const touchX = (0, _reactNativeReanimated.useSharedValue)(0);
|
||||||
|
const translationX = (0, _reactNativeReanimated.useSharedValue)(getDrawerTranslationX(open));
|
||||||
|
@@ -158,40 +159,43 @@ function Drawer({
|
||||||
|
}, [getDrawerTranslationX, handleAnimationEnd, handleAnimationStart, onClose, onOpen, touchStartX, touchX, translationX]);
|
||||||
|
React.useEffect(() => toggleDrawer(open), [open, toggleDrawer]);
|
||||||
|
const startX = (0, _reactNativeReanimated.useSharedValue)(0);
|
||||||
|
- let pan = _GestureHandler.Gesture?.Pan().onBegin(event => {
|
||||||
|
- 'worklet';
|
||||||
|
+ const pan = React.useMemo(() => {
|
||||||
|
+ let panGesture = _GestureHandler.Gesture?.Pan().onBegin(event => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- startX.value = translationX.value;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- touchStartX.value = event.x;
|
||||||
|
- }).onStart(() => {
|
||||||
|
- 'worklet';
|
||||||
|
+ startX.value = translationX.value;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ touchStartX.value = event.x;
|
||||||
|
+ }).onStart(() => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- (0, _reactNativeReanimated.runOnJS)(onGestureBegin)();
|
||||||
|
- }).onChange(event => {
|
||||||
|
- 'worklet';
|
||||||
|
+ (0, _reactNativeReanimated.runOnJS)(onGestureBegin)();
|
||||||
|
+ }).onChange(event => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- touchX.value = event.x;
|
||||||
|
- translationX.value = startX.value + event.translationX;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- }).onEnd((event, success) => {
|
||||||
|
- 'worklet';
|
||||||
|
+ touchX.value = event.x;
|
||||||
|
+ translationX.value = startX.value + event.translationX;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ }).onEnd((event, success) => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- if (!success) {
|
||||||
|
- (0, _reactNativeReanimated.runOnJS)(onGestureAbort)();
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ if (!success) {
|
||||||
|
+ (0, _reactNativeReanimated.runOnJS)(onGestureAbort)();
|
||||||
|
+ }
|
||||||
|
+ const nextOpen = Math.abs(event.translationX) > SWIPE_MIN_OFFSET && Math.abs(event.translationX) > swipeMinVelocity || Math.abs(event.translationX) > swipeMinDistance ? drawerPosition === 'left' ?
|
||||||
|
+ // If swiped to right, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) > 0 :
|
||||||
|
+ // If swiped to left, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) < 0 : open;
|
||||||
|
+ toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
+ (0, _reactNativeReanimated.runOnJS)(onGestureFinish)();
|
||||||
|
+ }).activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).hitSlop(hitSlop).enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
+ if (panGesture && configureGestureHandler) {
|
||||||
|
+ panGesture = configureGestureHandler(panGesture);
|
||||||
|
}
|
||||||
|
- const nextOpen = Math.abs(event.translationX) > SWIPE_MIN_OFFSET && Math.abs(event.translationX) > swipeMinVelocity || Math.abs(event.translationX) > swipeMinDistance ? drawerPosition === 'left' ?
|
||||||
|
- // If swiped to right, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) > 0 :
|
||||||
|
- // If swiped to left, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) < 0 : open;
|
||||||
|
- toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
- (0, _reactNativeReanimated.runOnJS)(onGestureFinish)();
|
||||||
|
- }).activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).hitSlop(hitSlop).enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
- if (pan && configureGestureHandler) {
|
||||||
|
- pan = configureGestureHandler(pan);
|
||||||
|
- }
|
||||||
|
+ return panGesture;
|
||||||
|
+ }, [configureGestureHandler, drawerPosition, drawerType, gestureState, hitSlop, onGestureBegin, onGestureAbort, onGestureFinish, open, startX, swipeEnabled, swipeMinDistance, swipeMinVelocity, toggleDrawer, touchStartX, touchX, translationX]);
|
||||||
|
const translateX = (0, _reactNativeReanimated.useDerivedValue)(() => {
|
||||||
|
// Comment stolen from react-native-gesture-handler/DrawerLayout
|
||||||
|
//
|
||||||
|
@@ -254,35 +258,38 @@ function Drawer({
|
||||||
|
style: [styles.container, style],
|
||||||
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerProgressContext.DrawerProgressContext.Provider, {
|
||||||
|
value: progress,
|
||||||
|
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_GestureHandler.GestureDetector, {
|
||||||
|
- gesture: pan,
|
||||||
|
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
|
||||||
|
- style: [styles.main, {
|
||||||
|
- flexDirection: drawerType === 'permanent' ? isRight && direction === 'ltr' || !isRight && direction === 'rtl' ? 'row' : 'row-reverse' : 'row'
|
||||||
|
- }],
|
||||||
|
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
|
||||||
|
- style: [styles.content, contentAnimatedStyle],
|
||||||
|
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
||||||
|
- accessibilityElementsHidden: isOpen && drawerType !== 'permanent',
|
||||||
|
- importantForAccessibility: isOpen && drawerType !== 'permanent' ? 'no-hide-descendants' : 'auto',
|
||||||
|
- style: styles.content,
|
||||||
|
- children: children
|
||||||
|
- }), drawerType !== 'permanent' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Overlay.Overlay, {
|
||||||
|
- open: open,
|
||||||
|
- progress: progress,
|
||||||
|
- onPress: () => toggleDrawer(false),
|
||||||
|
- style: overlayStyle,
|
||||||
|
- accessibilityLabel: overlayAccessibilityLabel
|
||||||
|
- }) : null]
|
||||||
|
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
||||||
|
- removeClippedSubviews: _reactNative.Platform.OS !== 'ios',
|
||||||
|
- style: [styles.drawer, {
|
||||||
|
- width: drawerWidth,
|
||||||
|
- position: drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
- zIndex: drawerType === 'back' ? -1 : 0
|
||||||
|
- }, drawerAnimatedStyle, drawerStyle],
|
||||||
|
- children: renderDrawerContent()
|
||||||
|
- })]
|
||||||
|
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerGestureContext.DrawerGestureContext.Provider, {
|
||||||
|
+ value: pan,
|
||||||
|
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_GestureHandler.GestureDetector, {
|
||||||
|
+ gesture: pan,
|
||||||
|
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
|
||||||
|
+ style: [styles.main, {
|
||||||
|
+ flexDirection: drawerType === 'permanent' ? isRight && direction === 'ltr' || !isRight && direction === 'rtl' ? 'row' : 'row-reverse' : 'row'
|
||||||
|
+ }],
|
||||||
|
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
|
||||||
|
+ style: [styles.content, contentAnimatedStyle],
|
||||||
|
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
||||||
|
+ accessibilityElementsHidden: isOpen && drawerType !== 'permanent',
|
||||||
|
+ importantForAccessibility: isOpen && drawerType !== 'permanent' ? 'no-hide-descendants' : 'auto',
|
||||||
|
+ style: styles.content,
|
||||||
|
+ children: children
|
||||||
|
+ }), drawerType !== 'permanent' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Overlay.Overlay, {
|
||||||
|
+ open: open,
|
||||||
|
+ progress: progress,
|
||||||
|
+ onPress: () => toggleDrawer(false),
|
||||||
|
+ style: overlayStyle,
|
||||||
|
+ accessibilityLabel: overlayAccessibilityLabel
|
||||||
|
+ }) : null]
|
||||||
|
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
||||||
|
+ removeClippedSubviews: _reactNative.Platform.OS !== 'ios',
|
||||||
|
+ style: [styles.drawer, {
|
||||||
|
+ width: drawerWidth,
|
||||||
|
+ position: drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
+ zIndex: drawerType === 'back' ? -1 : 0
|
||||||
|
+ }, drawerAnimatedStyle, drawerStyle],
|
||||||
|
+ children: renderDrawerContent()
|
||||||
|
+ })]
|
||||||
|
+ })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/module/index.js b/node_modules/react-native-drawer-layout/lib/module/index.js
|
||||||
|
index a600e51..f08275c 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/module/index.js
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/module/index.js
|
||||||
|
@@ -1,5 +1,6 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
+export { DrawerGestureContext } from "./utils/DrawerGestureContext.js";
|
||||||
|
export { DrawerProgressContext } from "./utils/DrawerProgressContext.js";
|
||||||
|
export { useDrawerProgress } from "./utils/useDrawerProgress.js";
|
||||||
|
export { Drawer } from './views/Drawer';
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/module/utils/DrawerGestureContext.js b/node_modules/react-native-drawer-layout/lib/module/utils/DrawerGestureContext.js
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..1adaa9c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/module/utils/DrawerGestureContext.js
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+"use strict";
|
||||||
|
+
|
||||||
|
+import * as React from 'react';
|
||||||
|
+export const DrawerGestureContext = /*#__PURE__*/React.createContext(undefined);
|
||||||
|
+//# sourceMappingURL=DrawerGestureContext.js.map
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js b/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||||
|
index 6d07126..981d9f8 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/module/views/Drawer.native.js
|
||||||
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
||||||
|
import { I18nManager, InteractionManager, Keyboard, Platform, StatusBar, StyleSheet, useWindowDimensions, View } from 'react-native';
|
||||||
|
import Animated, { interpolate, ReduceMotion, runOnJS, useAnimatedStyle, useDerivedValue, useSharedValue, withSpring } from 'react-native-reanimated';
|
||||||
|
import useLatestCallback from 'use-latest-callback';
|
||||||
|
+import { DrawerGestureContext } from "../utils/DrawerGestureContext.js";
|
||||||
|
import { DrawerProgressContext } from "../utils/DrawerProgressContext.js";
|
||||||
|
import { getDrawerWidth } from "../utils/getDrawerWidth.js";
|
||||||
|
import { Gesture, GestureDetector, GestureHandlerRootView, GestureState } from './GestureHandler';
|
||||||
|
@@ -72,38 +73,38 @@ export function Drawer({
|
||||||
|
return () => hideStatusBar(false);
|
||||||
|
}, [isOpen, hideStatusBarOnOpen, statusBarAnimation, hideStatusBar]);
|
||||||
|
const interactionHandleRef = React.useRef(null);
|
||||||
|
- const startInteraction = () => {
|
||||||
|
+ const startInteraction = React.useCallback(() => {
|
||||||
|
interactionHandleRef.current = InteractionManager.createInteractionHandle();
|
||||||
|
- };
|
||||||
|
- const endInteraction = () => {
|
||||||
|
+ }, []);
|
||||||
|
+ const endInteraction = React.useCallback(() => {
|
||||||
|
if (interactionHandleRef.current != null) {
|
||||||
|
InteractionManager.clearInteractionHandle(interactionHandleRef.current);
|
||||||
|
interactionHandleRef.current = null;
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
- const hideKeyboard = () => {
|
||||||
|
+ }, []);
|
||||||
|
+ const hideKeyboard = React.useCallback(() => {
|
||||||
|
if (keyboardDismissMode === 'on-drag') {
|
||||||
|
Keyboard.dismiss();
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
- const onGestureBegin = () => {
|
||||||
|
+ }, [keyboardDismissMode]);
|
||||||
|
+ const onGestureBegin = React.useCallback(() => {
|
||||||
|
onGestureStart?.();
|
||||||
|
startInteraction();
|
||||||
|
hideKeyboard();
|
||||||
|
hideStatusBar(true);
|
||||||
|
- };
|
||||||
|
- const onGestureFinish = () => {
|
||||||
|
+ }, [onGestureStart, startInteraction, hideKeyboard, hideStatusBar]);
|
||||||
|
+ const onGestureFinish = React.useCallback(() => {
|
||||||
|
onGestureEnd?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
- const onGestureAbort = () => {
|
||||||
|
+ }, [onGestureEnd, endInteraction]);
|
||||||
|
+ const onGestureAbort = React.useCallback(() => {
|
||||||
|
onGestureCancel?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
+ }, [onGestureCancel, endInteraction]);
|
||||||
|
|
||||||
|
// FIXME: Currently hitSlop is broken when on Android when drawer is on right
|
||||||
|
// https://github.com/software-mansion/react-native-gesture-handler/issues/569
|
||||||
|
- const hitSlop = isRight ?
|
||||||
|
+ const hitSlop = React.useMemo(() => isRight ?
|
||||||
|
// Extend hitSlop to the side of the screen when drawer is closed
|
||||||
|
// This lets the user drag the drawer from the side of the screen
|
||||||
|
{
|
||||||
|
@@ -112,7 +113,7 @@ export function Drawer({
|
||||||
|
} : {
|
||||||
|
left: 0,
|
||||||
|
width: isOpen ? undefined : swipeEdgeWidth
|
||||||
|
- };
|
||||||
|
+ }, [isRight, isOpen, swipeEdgeWidth]);
|
||||||
|
const touchStartX = useSharedValue(0);
|
||||||
|
const touchX = useSharedValue(0);
|
||||||
|
const translationX = useSharedValue(getDrawerTranslationX(open));
|
||||||
|
@@ -151,40 +152,43 @@ export function Drawer({
|
||||||
|
}, [getDrawerTranslationX, handleAnimationEnd, handleAnimationStart, onClose, onOpen, touchStartX, touchX, translationX]);
|
||||||
|
React.useEffect(() => toggleDrawer(open), [open, toggleDrawer]);
|
||||||
|
const startX = useSharedValue(0);
|
||||||
|
- let pan = Gesture?.Pan().onBegin(event => {
|
||||||
|
- 'worklet';
|
||||||
|
+ const pan = React.useMemo(() => {
|
||||||
|
+ let panGesture = Gesture?.Pan().onBegin(event => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- startX.value = translationX.value;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- touchStartX.value = event.x;
|
||||||
|
- }).onStart(() => {
|
||||||
|
- 'worklet';
|
||||||
|
+ startX.value = translationX.value;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ touchStartX.value = event.x;
|
||||||
|
+ }).onStart(() => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- runOnJS(onGestureBegin)();
|
||||||
|
- }).onChange(event => {
|
||||||
|
- 'worklet';
|
||||||
|
+ runOnJS(onGestureBegin)();
|
||||||
|
+ }).onChange(event => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- touchX.value = event.x;
|
||||||
|
- translationX.value = startX.value + event.translationX;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- }).onEnd((event, success) => {
|
||||||
|
- 'worklet';
|
||||||
|
+ touchX.value = event.x;
|
||||||
|
+ translationX.value = startX.value + event.translationX;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ }).onEnd((event, success) => {
|
||||||
|
+ 'worklet';
|
||||||
|
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- if (!success) {
|
||||||
|
- runOnJS(onGestureAbort)();
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ if (!success) {
|
||||||
|
+ runOnJS(onGestureAbort)();
|
||||||
|
+ }
|
||||||
|
+ const nextOpen = Math.abs(event.translationX) > SWIPE_MIN_OFFSET && Math.abs(event.translationX) > swipeMinVelocity || Math.abs(event.translationX) > swipeMinDistance ? drawerPosition === 'left' ?
|
||||||
|
+ // If swiped to right, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) > 0 :
|
||||||
|
+ // If swiped to left, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) < 0 : open;
|
||||||
|
+ toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
+ runOnJS(onGestureFinish)();
|
||||||
|
+ }).activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).hitSlop(hitSlop).enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
+ if (panGesture && configureGestureHandler) {
|
||||||
|
+ panGesture = configureGestureHandler(panGesture);
|
||||||
|
}
|
||||||
|
- const nextOpen = Math.abs(event.translationX) > SWIPE_MIN_OFFSET && Math.abs(event.translationX) > swipeMinVelocity || Math.abs(event.translationX) > swipeMinDistance ? drawerPosition === 'left' ?
|
||||||
|
- // If swiped to right, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) > 0 :
|
||||||
|
- // If swiped to left, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) < 0 : open;
|
||||||
|
- toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
- runOnJS(onGestureFinish)();
|
||||||
|
- }).activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]).hitSlop(hitSlop).enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
- if (pan && configureGestureHandler) {
|
||||||
|
- pan = configureGestureHandler(pan);
|
||||||
|
- }
|
||||||
|
+ return panGesture;
|
||||||
|
+ }, [configureGestureHandler, drawerPosition, drawerType, gestureState, hitSlop, onGestureBegin, onGestureAbort, onGestureFinish, open, startX, swipeEnabled, swipeMinDistance, swipeMinVelocity, toggleDrawer, touchStartX, touchX, translationX]);
|
||||||
|
const translateX = useDerivedValue(() => {
|
||||||
|
// Comment stolen from react-native-gesture-handler/DrawerLayout
|
||||||
|
//
|
||||||
|
@@ -247,35 +251,38 @@ export function Drawer({
|
||||||
|
style: [styles.container, style],
|
||||||
|
children: /*#__PURE__*/_jsx(DrawerProgressContext.Provider, {
|
||||||
|
value: progress,
|
||||||
|
- children: /*#__PURE__*/_jsx(GestureDetector, {
|
||||||
|
- gesture: pan,
|
||||||
|
- children: /*#__PURE__*/_jsxs(Animated.View, {
|
||||||
|
- style: [styles.main, {
|
||||||
|
- flexDirection: drawerType === 'permanent' ? isRight && direction === 'ltr' || !isRight && direction === 'rtl' ? 'row' : 'row-reverse' : 'row'
|
||||||
|
- }],
|
||||||
|
- children: [/*#__PURE__*/_jsxs(Animated.View, {
|
||||||
|
- style: [styles.content, contentAnimatedStyle],
|
||||||
|
- children: [/*#__PURE__*/_jsx(View, {
|
||||||
|
- accessibilityElementsHidden: isOpen && drawerType !== 'permanent',
|
||||||
|
- importantForAccessibility: isOpen && drawerType !== 'permanent' ? 'no-hide-descendants' : 'auto',
|
||||||
|
- style: styles.content,
|
||||||
|
- children: children
|
||||||
|
- }), drawerType !== 'permanent' ? /*#__PURE__*/_jsx(Overlay, {
|
||||||
|
- open: open,
|
||||||
|
- progress: progress,
|
||||||
|
- onPress: () => toggleDrawer(false),
|
||||||
|
- style: overlayStyle,
|
||||||
|
- accessibilityLabel: overlayAccessibilityLabel
|
||||||
|
- }) : null]
|
||||||
|
- }), /*#__PURE__*/_jsx(Animated.View, {
|
||||||
|
- removeClippedSubviews: Platform.OS !== 'ios',
|
||||||
|
- style: [styles.drawer, {
|
||||||
|
- width: drawerWidth,
|
||||||
|
- position: drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
- zIndex: drawerType === 'back' ? -1 : 0
|
||||||
|
- }, drawerAnimatedStyle, drawerStyle],
|
||||||
|
- children: renderDrawerContent()
|
||||||
|
- })]
|
||||||
|
+ children: /*#__PURE__*/_jsx(DrawerGestureContext.Provider, {
|
||||||
|
+ value: pan,
|
||||||
|
+ children: /*#__PURE__*/_jsx(GestureDetector, {
|
||||||
|
+ gesture: pan,
|
||||||
|
+ children: /*#__PURE__*/_jsxs(Animated.View, {
|
||||||
|
+ style: [styles.main, {
|
||||||
|
+ flexDirection: drawerType === 'permanent' ? isRight && direction === 'ltr' || !isRight && direction === 'rtl' ? 'row' : 'row-reverse' : 'row'
|
||||||
|
+ }],
|
||||||
|
+ children: [/*#__PURE__*/_jsxs(Animated.View, {
|
||||||
|
+ style: [styles.content, contentAnimatedStyle],
|
||||||
|
+ children: [/*#__PURE__*/_jsx(View, {
|
||||||
|
+ accessibilityElementsHidden: isOpen && drawerType !== 'permanent',
|
||||||
|
+ importantForAccessibility: isOpen && drawerType !== 'permanent' ? 'no-hide-descendants' : 'auto',
|
||||||
|
+ style: styles.content,
|
||||||
|
+ children: children
|
||||||
|
+ }), drawerType !== 'permanent' ? /*#__PURE__*/_jsx(Overlay, {
|
||||||
|
+ open: open,
|
||||||
|
+ progress: progress,
|
||||||
|
+ onPress: () => toggleDrawer(false),
|
||||||
|
+ style: overlayStyle,
|
||||||
|
+ accessibilityLabel: overlayAccessibilityLabel
|
||||||
|
+ }) : null]
|
||||||
|
+ }), /*#__PURE__*/_jsx(Animated.View, {
|
||||||
|
+ removeClippedSubviews: Platform.OS !== 'ios',
|
||||||
|
+ style: [styles.drawer, {
|
||||||
|
+ width: drawerWidth,
|
||||||
|
+ position: drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
+ zIndex: drawerType === 'back' ? -1 : 0
|
||||||
|
+ }, drawerAnimatedStyle, drawerStyle],
|
||||||
|
+ children: renderDrawerContent()
|
||||||
|
+ })]
|
||||||
|
+ })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/index.d.ts b/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/index.d.ts
|
||||||
|
index 7e978f0..a8bce18 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/index.d.ts
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/index.d.ts
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
+export { DrawerGestureContext } from './utils/DrawerGestureContext';
|
||||||
|
export { DrawerProgressContext } from './utils/DrawerProgressContext';
|
||||||
|
export { useDrawerProgress } from './utils/useDrawerProgress';
|
||||||
|
export { Drawer } from './views/Drawer';
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/utils/DrawerGestureContext.d.ts b/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/utils/DrawerGestureContext.d.ts
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..33ffbeb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/typescript/commonjs/src/utils/DrawerGestureContext.d.ts
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+import * as React from 'react';
|
||||||
|
+export declare const DrawerGestureContext: React.Context<import("react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture").PanGesture | undefined>;
|
||||||
|
+//# sourceMappingURL=DrawerGestureContext.d.ts.map
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/typescript/module/src/index.d.ts b/node_modules/react-native-drawer-layout/lib/typescript/module/src/index.d.ts
|
||||||
|
index 7e978f0..a8bce18 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/lib/typescript/module/src/index.d.ts
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/typescript/module/src/index.d.ts
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
+export { DrawerGestureContext } from './utils/DrawerGestureContext';
|
||||||
|
export { DrawerProgressContext } from './utils/DrawerProgressContext';
|
||||||
|
export { useDrawerProgress } from './utils/useDrawerProgress';
|
||||||
|
export { Drawer } from './views/Drawer';
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/lib/typescript/module/src/utils/DrawerGestureContext.d.ts b/node_modules/react-native-drawer-layout/lib/typescript/module/src/utils/DrawerGestureContext.d.ts
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..33ffbeb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/lib/typescript/module/src/utils/DrawerGestureContext.d.ts
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+import * as React from 'react';
|
||||||
|
+export declare const DrawerGestureContext: React.Context<import("react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture").PanGesture | undefined>;
|
||||||
|
+//# sourceMappingURL=DrawerGestureContext.d.ts.map
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/src/index.tsx b/node_modules/react-native-drawer-layout/src/index.tsx
|
||||||
|
index 0aa6f53..61a37cf 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/src/index.tsx
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/src/index.tsx
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
+export { DrawerGestureContext } from './utils/DrawerGestureContext';
|
||||||
|
export { DrawerProgressContext } from './utils/DrawerProgressContext';
|
||||||
|
export { useDrawerProgress } from './utils/useDrawerProgress';
|
||||||
|
export { Drawer } from './views/Drawer';
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/src/utils/DrawerGestureContext.tsx b/node_modules/react-native-drawer-layout/src/utils/DrawerGestureContext.tsx
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..3aac957
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/src/utils/DrawerGestureContext.tsx
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+import * as React from 'react';
|
||||||
|
+import type { PanGesture } from 'react-native-gesture-handler';
|
||||||
|
+
|
||||||
|
+export const DrawerGestureContext = React.createContext<PanGesture | undefined>(
|
||||||
|
+ undefined
|
||||||
|
+);
|
||||||
|
diff --git a/node_modules/react-native-drawer-layout/src/views/Drawer.native.tsx b/node_modules/react-native-drawer-layout/src/views/Drawer.native.tsx
|
||||||
|
index 9c40f41..ee5d075 100644
|
||||||
|
--- a/node_modules/react-native-drawer-layout/src/views/Drawer.native.tsx
|
||||||
|
+++ b/node_modules/react-native-drawer-layout/src/views/Drawer.native.tsx
|
||||||
|
@@ -21,6 +21,7 @@ import Animated, {
|
||||||
|
import useLatestCallback from 'use-latest-callback';
|
||||||
|
|
||||||
|
import type { DrawerProps } from '../types';
|
||||||
|
+import { DrawerGestureContext } from '../utils/DrawerGestureContext';
|
||||||
|
import { DrawerProgressContext } from '../utils/DrawerProgressContext';
|
||||||
|
import { getDrawerWidth } from '../utils/getDrawerWidth';
|
||||||
|
import {
|
||||||
|
@@ -110,47 +111,51 @@ export function Drawer({
|
||||||
|
|
||||||
|
const interactionHandleRef = React.useRef<number | null>(null);
|
||||||
|
|
||||||
|
- const startInteraction = () => {
|
||||||
|
+ const startInteraction = React.useCallback(() => {
|
||||||
|
interactionHandleRef.current = InteractionManager.createInteractionHandle();
|
||||||
|
- };
|
||||||
|
+ }, []);
|
||||||
|
|
||||||
|
- const endInteraction = () => {
|
||||||
|
+ const endInteraction = React.useCallback(() => {
|
||||||
|
if (interactionHandleRef.current != null) {
|
||||||
|
InteractionManager.clearInteractionHandle(interactionHandleRef.current);
|
||||||
|
interactionHandleRef.current = null;
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
+ }, []);
|
||||||
|
|
||||||
|
- const hideKeyboard = () => {
|
||||||
|
+ const hideKeyboard = React.useCallback(() => {
|
||||||
|
if (keyboardDismissMode === 'on-drag') {
|
||||||
|
Keyboard.dismiss();
|
||||||
|
}
|
||||||
|
- };
|
||||||
|
+ }, [keyboardDismissMode]);
|
||||||
|
|
||||||
|
- const onGestureBegin = () => {
|
||||||
|
+ const onGestureBegin = React.useCallback(() => {
|
||||||
|
onGestureStart?.();
|
||||||
|
startInteraction();
|
||||||
|
hideKeyboard();
|
||||||
|
hideStatusBar(true);
|
||||||
|
- };
|
||||||
|
+ }, [onGestureStart, startInteraction, hideKeyboard, hideStatusBar]);
|
||||||
|
|
||||||
|
- const onGestureFinish = () => {
|
||||||
|
+ const onGestureFinish = React.useCallback(() => {
|
||||||
|
onGestureEnd?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
+ }, [onGestureEnd, endInteraction]);
|
||||||
|
|
||||||
|
- const onGestureAbort = () => {
|
||||||
|
+ const onGestureAbort = React.useCallback(() => {
|
||||||
|
onGestureCancel?.();
|
||||||
|
endInteraction();
|
||||||
|
- };
|
||||||
|
+ }, [onGestureCancel, endInteraction]);
|
||||||
|
|
||||||
|
// FIXME: Currently hitSlop is broken when on Android when drawer is on right
|
||||||
|
// https://github.com/software-mansion/react-native-gesture-handler/issues/569
|
||||||
|
- const hitSlop = isRight
|
||||||
|
- ? // Extend hitSlop to the side of the screen when drawer is closed
|
||||||
|
- // This lets the user drag the drawer from the side of the screen
|
||||||
|
- { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
|
||||||
|
- : { left: 0, width: isOpen ? undefined : swipeEdgeWidth };
|
||||||
|
+ const hitSlop = React.useMemo(
|
||||||
|
+ () =>
|
||||||
|
+ isRight
|
||||||
|
+ ? // Extend hitSlop to the side of the screen when drawer is closed
|
||||||
|
+ // This lets the user drag the drawer from the side of the screen
|
||||||
|
+ { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
|
||||||
|
+ : { left: 0, width: isOpen ? undefined : swipeEdgeWidth },
|
||||||
|
+ [isRight, isOpen, swipeEdgeWidth]
|
||||||
|
+ );
|
||||||
|
|
||||||
|
const touchStartX = useSharedValue(0);
|
||||||
|
const touchX = useSharedValue(0);
|
||||||
|
@@ -217,53 +222,76 @@ export function Drawer({
|
||||||
|
|
||||||
|
const startX = useSharedValue(0);
|
||||||
|
|
||||||
|
- let pan = Gesture?.Pan()
|
||||||
|
- .onBegin((event) => {
|
||||||
|
- 'worklet';
|
||||||
|
- startX.value = translationX.value;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- touchStartX.value = event.x;
|
||||||
|
- })
|
||||||
|
- .onStart(() => {
|
||||||
|
- 'worklet';
|
||||||
|
- runOnJS(onGestureBegin)();
|
||||||
|
- })
|
||||||
|
- .onChange((event) => {
|
||||||
|
- 'worklet';
|
||||||
|
- touchX.value = event.x;
|
||||||
|
- translationX.value = startX.value + event.translationX;
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
- })
|
||||||
|
- .onEnd((event, success) => {
|
||||||
|
- 'worklet';
|
||||||
|
- gestureState.value = event.state;
|
||||||
|
-
|
||||||
|
- if (!success) {
|
||||||
|
- runOnJS(onGestureAbort)();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- const nextOpen =
|
||||||
|
- (Math.abs(event.translationX) > SWIPE_MIN_OFFSET &&
|
||||||
|
- Math.abs(event.translationX) > swipeMinVelocity) ||
|
||||||
|
- Math.abs(event.translationX) > swipeMinDistance
|
||||||
|
- ? drawerPosition === 'left'
|
||||||
|
- ? // If swiped to right, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) > 0
|
||||||
|
- : // If swiped to left, open the drawer, otherwise close it
|
||||||
|
- (event.velocityX === 0 ? event.translationX : event.velocityX) < 0
|
||||||
|
- : open;
|
||||||
|
-
|
||||||
|
- toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
- runOnJS(onGestureFinish)();
|
||||||
|
- })
|
||||||
|
- .activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET])
|
||||||
|
- .failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET])
|
||||||
|
- .hitSlop(hitSlop)
|
||||||
|
- .enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
-
|
||||||
|
- if (pan && configureGestureHandler) {
|
||||||
|
- pan = configureGestureHandler(pan);
|
||||||
|
- }
|
||||||
|
+ const pan = React.useMemo(() => {
|
||||||
|
+ let panGesture = Gesture?.Pan()
|
||||||
|
+ .onBegin((event) => {
|
||||||
|
+ 'worklet';
|
||||||
|
+ startX.value = translationX.value;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ touchStartX.value = event.x;
|
||||||
|
+ })
|
||||||
|
+ .onStart(() => {
|
||||||
|
+ 'worklet';
|
||||||
|
+ runOnJS(onGestureBegin)();
|
||||||
|
+ })
|
||||||
|
+ .onChange((event) => {
|
||||||
|
+ 'worklet';
|
||||||
|
+ touchX.value = event.x;
|
||||||
|
+ translationX.value = startX.value + event.translationX;
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+ })
|
||||||
|
+ .onEnd((event, success) => {
|
||||||
|
+ 'worklet';
|
||||||
|
+ gestureState.value = event.state;
|
||||||
|
+
|
||||||
|
+ if (!success) {
|
||||||
|
+ runOnJS(onGestureAbort)();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const nextOpen =
|
||||||
|
+ (Math.abs(event.translationX) > SWIPE_MIN_OFFSET &&
|
||||||
|
+ Math.abs(event.translationX) > swipeMinVelocity) ||
|
||||||
|
+ Math.abs(event.translationX) > swipeMinDistance
|
||||||
|
+ ? drawerPosition === 'left'
|
||||||
|
+ ? // If swiped to right, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) >
|
||||||
|
+ 0
|
||||||
|
+ : // If swiped to left, open the drawer, otherwise close it
|
||||||
|
+ (event.velocityX === 0 ? event.translationX : event.velocityX) <
|
||||||
|
+ 0
|
||||||
|
+ : open;
|
||||||
|
+
|
||||||
|
+ toggleDrawer(nextOpen, event.velocityX);
|
||||||
|
+ runOnJS(onGestureFinish)();
|
||||||
|
+ })
|
||||||
|
+ .activeOffsetX([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET])
|
||||||
|
+ .failOffsetY([-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET])
|
||||||
|
+ .hitSlop(hitSlop)
|
||||||
|
+ .enabled(drawerType !== 'permanent' && swipeEnabled);
|
||||||
|
+
|
||||||
|
+ if (panGesture && configureGestureHandler) {
|
||||||
|
+ panGesture = configureGestureHandler(panGesture);
|
||||||
|
+ }
|
||||||
|
+ return panGesture;
|
||||||
|
+ }, [
|
||||||
|
+ configureGestureHandler,
|
||||||
|
+ drawerPosition,
|
||||||
|
+ drawerType,
|
||||||
|
+ gestureState,
|
||||||
|
+ hitSlop,
|
||||||
|
+ onGestureBegin,
|
||||||
|
+ onGestureAbort,
|
||||||
|
+ onGestureFinish,
|
||||||
|
+ open,
|
||||||
|
+ startX,
|
||||||
|
+ swipeEnabled,
|
||||||
|
+ swipeMinDistance,
|
||||||
|
+ swipeMinVelocity,
|
||||||
|
+ toggleDrawer,
|
||||||
|
+ touchStartX,
|
||||||
|
+ touchX,
|
||||||
|
+ translationX,
|
||||||
|
+ ]);
|
||||||
|
|
||||||
|
const translateX = useDerivedValue(() => {
|
||||||
|
// Comment stolen from react-native-gesture-handler/DrawerLayout
|
||||||
|
@@ -376,64 +404,66 @@ export function Drawer({
|
||||||
|
return (
|
||||||
|
<GestureHandlerRootView style={[styles.container, style]}>
|
||||||
|
<DrawerProgressContext.Provider value={progress}>
|
||||||
|
- <GestureDetector gesture={pan}>
|
||||||
|
- {/* Immediate child of gesture handler needs to be an Animated.View */}
|
||||||
|
- <Animated.View
|
||||||
|
- style={[
|
||||||
|
- styles.main,
|
||||||
|
- {
|
||||||
|
- flexDirection:
|
||||||
|
- drawerType === 'permanent'
|
||||||
|
- ? (isRight && direction === 'ltr') ||
|
||||||
|
- (!isRight && direction === 'rtl')
|
||||||
|
- ? 'row'
|
||||||
|
- : 'row-reverse'
|
||||||
|
- : 'row',
|
||||||
|
- },
|
||||||
|
- ]}
|
||||||
|
- >
|
||||||
|
- <Animated.View style={[styles.content, contentAnimatedStyle]}>
|
||||||
|
- <View
|
||||||
|
- accessibilityElementsHidden={
|
||||||
|
- isOpen && drawerType !== 'permanent'
|
||||||
|
- }
|
||||||
|
- importantForAccessibility={
|
||||||
|
- isOpen && drawerType !== 'permanent'
|
||||||
|
- ? 'no-hide-descendants'
|
||||||
|
- : 'auto'
|
||||||
|
- }
|
||||||
|
- style={styles.content}
|
||||||
|
- >
|
||||||
|
- {children}
|
||||||
|
- </View>
|
||||||
|
- {drawerType !== 'permanent' ? (
|
||||||
|
- <Overlay
|
||||||
|
- open={open}
|
||||||
|
- progress={progress}
|
||||||
|
- onPress={() => toggleDrawer(false)}
|
||||||
|
- style={overlayStyle}
|
||||||
|
- accessibilityLabel={overlayAccessibilityLabel}
|
||||||
|
- />
|
||||||
|
- ) : null}
|
||||||
|
- </Animated.View>
|
||||||
|
+ <DrawerGestureContext.Provider value={pan}>
|
||||||
|
+ <GestureDetector gesture={pan}>
|
||||||
|
+ {/* Immediate child of gesture handler needs to be an Animated.View */}
|
||||||
|
<Animated.View
|
||||||
|
- removeClippedSubviews={Platform.OS !== 'ios'}
|
||||||
|
style={[
|
||||||
|
- styles.drawer,
|
||||||
|
+ styles.main,
|
||||||
|
{
|
||||||
|
- width: drawerWidth,
|
||||||
|
- position:
|
||||||
|
- drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
- zIndex: drawerType === 'back' ? -1 : 0,
|
||||||
|
+ flexDirection:
|
||||||
|
+ drawerType === 'permanent'
|
||||||
|
+ ? (isRight && direction === 'ltr') ||
|
||||||
|
+ (!isRight && direction === 'rtl')
|
||||||
|
+ ? 'row'
|
||||||
|
+ : 'row-reverse'
|
||||||
|
+ : 'row',
|
||||||
|
},
|
||||||
|
- drawerAnimatedStyle,
|
||||||
|
- drawerStyle,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
- {renderDrawerContent()}
|
||||||
|
+ <Animated.View style={[styles.content, contentAnimatedStyle]}>
|
||||||
|
+ <View
|
||||||
|
+ accessibilityElementsHidden={
|
||||||
|
+ isOpen && drawerType !== 'permanent'
|
||||||
|
+ }
|
||||||
|
+ importantForAccessibility={
|
||||||
|
+ isOpen && drawerType !== 'permanent'
|
||||||
|
+ ? 'no-hide-descendants'
|
||||||
|
+ : 'auto'
|
||||||
|
+ }
|
||||||
|
+ style={styles.content}
|
||||||
|
+ >
|
||||||
|
+ {children}
|
||||||
|
+ </View>
|
||||||
|
+ {drawerType !== 'permanent' ? (
|
||||||
|
+ <Overlay
|
||||||
|
+ open={open}
|
||||||
|
+ progress={progress}
|
||||||
|
+ onPress={() => toggleDrawer(false)}
|
||||||
|
+ style={overlayStyle}
|
||||||
|
+ accessibilityLabel={overlayAccessibilityLabel}
|
||||||
|
+ />
|
||||||
|
+ ) : null}
|
||||||
|
+ </Animated.View>
|
||||||
|
+ <Animated.View
|
||||||
|
+ removeClippedSubviews={Platform.OS !== 'ios'}
|
||||||
|
+ style={[
|
||||||
|
+ styles.drawer,
|
||||||
|
+ {
|
||||||
|
+ width: drawerWidth,
|
||||||
|
+ position:
|
||||||
|
+ drawerType === 'permanent' ? 'relative' : 'absolute',
|
||||||
|
+ zIndex: drawerType === 'back' ? -1 : 0,
|
||||||
|
+ },
|
||||||
|
+ drawerAnimatedStyle,
|
||||||
|
+ drawerStyle,
|
||||||
|
+ ]}
|
||||||
|
+ >
|
||||||
|
+ {renderDrawerContent()}
|
||||||
|
+ </Animated.View>
|
||||||
|
</Animated.View>
|
||||||
|
- </Animated.View>
|
||||||
|
- </GestureDetector>
|
||||||
|
+ </GestureDetector>
|
||||||
|
+ </DrawerGestureContext.Provider>
|
||||||
|
</DrawerProgressContext.Provider>
|
||||||
|
</GestureHandlerRootView>
|
||||||
|
);
|
||||||
@@ -14,7 +14,7 @@ import {cleanError} from '#/lib/strings/errors'
|
|||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {enforceLen} from '#/lib/strings/helpers'
|
import {enforceLen} from '#/lib/strings/helpers'
|
||||||
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
||||||
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {Pager} from '#/view/com/pager/Pager'
|
import {Pager} from '#/view/com/pager/Pager'
|
||||||
import {TabBar} from '#/view/com/pager/TabBar'
|
import {TabBar} from '#/view/com/pager/TabBar'
|
||||||
import {Post} from '#/view/com/post/Post'
|
import {Post} from '#/view/com/post/Post'
|
||||||
@@ -63,7 +63,6 @@ export default function HashtagScreen({
|
|||||||
|
|
||||||
const [activeTab, setActiveTab] = React.useState(0)
|
const [activeTab, setActiveTab] = React.useState(0)
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
@@ -74,10 +73,9 @@ export default function HashtagScreen({
|
|||||||
const onPageSelected = React.useCallback(
|
const onPageSelected = React.useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
setMinimalShellMode(false)
|
setMinimalShellMode(false)
|
||||||
setDrawerSwipeDisabled(index > 0)
|
|
||||||
setActiveTab(index)
|
setActiveTab(index)
|
||||||
},
|
},
|
||||||
[setDrawerSwipeDisabled, setMinimalShellMode],
|
[setMinimalShellMode],
|
||||||
)
|
)
|
||||||
|
|
||||||
const sections = React.useMemo(() => {
|
const sections = React.useMemo(() => {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import React, {forwardRef} from 'react'
|
import React, {forwardRef, useCallback, useContext} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
import {DrawerGestureContext} from 'react-native-drawer-layout'
|
||||||
|
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
|
||||||
import PagerView, {
|
import PagerView, {
|
||||||
PagerViewOnPageScrollEventData,
|
PagerViewOnPageScrollEventData,
|
||||||
PagerViewOnPageSelectedEvent,
|
PagerViewOnPageSelectedEvent,
|
||||||
@@ -13,7 +15,9 @@ import Animated, {
|
|||||||
useHandler,
|
useHandler,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
|
import {useSetDrawerSwipeDisabled} from '#/state/shell'
|
||||||
import {atoms as a, native} from '#/alf'
|
import {atoms as a, native} from '#/alf'
|
||||||
|
|
||||||
export type PageSelectedEvent = PagerViewOnPageSelectedEvent
|
export type PageSelectedEvent = PagerViewOnPageSelectedEvent
|
||||||
@@ -58,6 +62,18 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
const [selectedPage, setSelectedPage] = React.useState(initialPage)
|
const [selectedPage, setSelectedPage] = React.useState(initialPage)
|
||||||
const pagerView = React.useRef<PagerView>(null)
|
const pagerView = React.useRef<PagerView>(null)
|
||||||
|
|
||||||
|
const [isIdle, setIsIdle] = React.useState(true)
|
||||||
|
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
const canSwipeDrawer = selectedPage === 0 && isIdle
|
||||||
|
setDrawerSwipeDisabled(!canSwipeDrawer)
|
||||||
|
return () => {
|
||||||
|
setDrawerSwipeDisabled(false)
|
||||||
|
}
|
||||||
|
}, [setDrawerSwipeDisabled, selectedPage, isIdle]),
|
||||||
|
)
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(ref, () => ({
|
||||||
setPage: (index: number) => {
|
setPage: (index: number) => {
|
||||||
pagerView.current?.setPage(index)
|
pagerView.current?.setPage(index)
|
||||||
@@ -96,6 +112,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
},
|
},
|
||||||
onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) {
|
onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) {
|
||||||
'worklet'
|
'worklet'
|
||||||
|
runOnJS(setIsIdle)(e.pageScrollState === 'idle')
|
||||||
if (dragState.get() === 'idle' && e.pageScrollState === 'settling') {
|
if (dragState.get() === 'idle' && e.pageScrollState === 'settling') {
|
||||||
// This is a programmatic scroll on Android.
|
// This is a programmatic scroll on Android.
|
||||||
// Stay "idle" to match iOS and avoid confusing downstream code.
|
// Stay "idle" to match iOS and avoid confusing downstream code.
|
||||||
@@ -113,6 +130,10 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
[parentOnPageScrollStateChanged],
|
[parentOnPageScrollStateChanged],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const drawerGesture = useContext(DrawerGestureContext)!
|
||||||
|
const nativeGesture =
|
||||||
|
Gesture.Native().requireExternalGestureToFail(drawerGesture)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={[a.flex_1, native(a.overflow_hidden)]}>
|
<View testID={testID} style={[a.flex_1, native(a.overflow_hidden)]}>
|
||||||
{renderTabBar({
|
{renderTabBar({
|
||||||
@@ -121,6 +142,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
dragProgress,
|
dragProgress,
|
||||||
dragState,
|
dragState,
|
||||||
})}
|
})}
|
||||||
|
<GestureDetector gesture={nativeGesture}>
|
||||||
<AnimatedPagerView
|
<AnimatedPagerView
|
||||||
ref={pagerView}
|
ref={pagerView}
|
||||||
style={[a.flex_1]}
|
style={[a.flex_1]}
|
||||||
@@ -128,6 +150,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
onPageScroll={handlePageScroll}>
|
onPageScroll={handlePageScroll}>
|
||||||
{children}
|
{children}
|
||||||
</AnimatedPagerView>
|
</AnimatedPagerView>
|
||||||
|
</GestureDetector>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {FeedParams} from '#/state/queries/post-feed'
|
|||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
||||||
import {FeedPage} from '#/view/com/feeds/FeedPage'
|
import {FeedPage} from '#/view/com/feeds/FeedPage'
|
||||||
@@ -127,15 +127,10 @@ function HomeScreenReady({
|
|||||||
|
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
setMinimalShellMode(false)
|
setMinimalShellMode(false)
|
||||||
setDrawerSwipeDisabled(selectedIndex > 0)
|
}, [setMinimalShellMode]),
|
||||||
return () => {
|
|
||||||
setDrawerSwipeDisabled(false)
|
|
||||||
}
|
|
||||||
}, [setDrawerSwipeDisabled, selectedIndex, setMinimalShellMode]),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
@@ -154,7 +149,6 @@ function HomeScreenReady({
|
|||||||
const onPageSelected = React.useCallback(
|
const onPageSelected = React.useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
setMinimalShellMode(false)
|
setMinimalShellMode(false)
|
||||||
setDrawerSwipeDisabled(index > 0)
|
|
||||||
const feed = allFeeds[index]
|
const feed = allFeeds[index]
|
||||||
// Mutate the ref before setting state to avoid the imperative syncing effect
|
// Mutate the ref before setting state to avoid the imperative syncing effect
|
||||||
// above from starting a loop on Android when swiping back and forth.
|
// above from starting a loop on Android when swiping back and forth.
|
||||||
@@ -166,7 +160,7 @@ function HomeScreenReady({
|
|||||||
feedUrl: feed,
|
feedUrl: feed,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
[setDrawerSwipeDisabled, setSelectedFeed, setMinimalShellMode, allFeeds],
|
[setSelectedFeed, setMinimalShellMode, allFeeds],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPressSelected = React.useCallback(() => {
|
const onPressSelected = React.useCallback(() => {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {resetProfilePostsQueries} from '#/state/queries/post-feed'
|
|||||||
import {useProfileQuery} from '#/state/queries/profile'
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {ProfileFeedgens} from '#/view/com/feeds/ProfileFeedgens'
|
import {ProfileFeedgens} from '#/view/com/feeds/ProfileFeedgens'
|
||||||
import {ProfileLists} from '#/view/com/lists/ProfileLists'
|
import {ProfileLists} from '#/view/com/lists/ProfileLists'
|
||||||
@@ -183,7 +183,6 @@ function ProfileScreenLoaded({
|
|||||||
})
|
})
|
||||||
const [currentPage, setCurrentPage] = React.useState(0)
|
const [currentPage, setCurrentPage] = React.useState(0)
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
|
||||||
|
|
||||||
const [scrollViewTag, setScrollViewTag] = React.useState<number | null>(null)
|
const [scrollViewTag, setScrollViewTag] = React.useState<number | null>(null)
|
||||||
|
|
||||||
@@ -307,15 +306,6 @@ function ProfileScreenLoaded({
|
|||||||
}, [setMinimalShellMode, currentPage, scrollSectionToTop]),
|
}, [setMinimalShellMode, currentPage, scrollSectionToTop]),
|
||||||
)
|
)
|
||||||
|
|
||||||
useFocusEffect(
|
|
||||||
React.useCallback(() => {
|
|
||||||
setDrawerSwipeDisabled(currentPage > 0)
|
|
||||||
return () => {
|
|
||||||
setDrawerSwipeDisabled(false)
|
|
||||||
}
|
|
||||||
}, [setDrawerSwipeDisabled, currentPage]),
|
|
||||||
)
|
|
||||||
|
|
||||||
// events
|
// events
|
||||||
// =
|
// =
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import {usePopularFeedsSearch} from '#/state/queries/feed'
|
|||||||
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useSetDrawerOpen} from '#/state/shell'
|
import {useSetDrawerOpen} from '#/state/shell'
|
||||||
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {Pager} from '#/view/com/pager/Pager'
|
import {Pager} from '#/view/com/pager/Pager'
|
||||||
import {TabBar} from '#/view/com/pager/TabBar'
|
import {TabBar} from '#/view/com/pager/TabBar'
|
||||||
import {Post} from '#/view/com/post/Post'
|
import {Post} from '#/view/com/post/Post'
|
||||||
@@ -471,7 +471,6 @@ let SearchScreenInner = ({
|
|||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isDesktop} = useWebMediaQueries()
|
||||||
const [activeTab, setActiveTab] = React.useState(0)
|
const [activeTab, setActiveTab] = React.useState(0)
|
||||||
@@ -480,10 +479,9 @@ let SearchScreenInner = ({
|
|||||||
const onPageSelected = React.useCallback(
|
const onPageSelected = React.useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
setMinimalShellMode(false)
|
setMinimalShellMode(false)
|
||||||
setDrawerSwipeDisabled(index > 0)
|
|
||||||
setActiveTab(index)
|
setActiveTab(index)
|
||||||
},
|
},
|
||||||
[setDrawerSwipeDisabled, setMinimalShellMode],
|
[setMinimalShellMode],
|
||||||
)
|
)
|
||||||
|
|
||||||
const sections = React.useMemo(() => {
|
const sections = React.useMemo(() => {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ function ShellInner() {
|
|||||||
}
|
}
|
||||||
}, [dedupe, navigation])
|
}, [dedupe, navigation])
|
||||||
|
|
||||||
|
const swipeEnabled = !canGoBack && hasSession && !isDrawerSwipeDisabled
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={[a.h_full]}>
|
<View style={[a.h_full]}>
|
||||||
@@ -98,12 +99,35 @@ function ShellInner() {
|
|||||||
<Drawer
|
<Drawer
|
||||||
renderDrawerContent={renderDrawerContent}
|
renderDrawerContent={renderDrawerContent}
|
||||||
drawerStyle={{width: Math.min(400, winDim.width * 0.8)}}
|
drawerStyle={{width: Math.min(400, winDim.width * 0.8)}}
|
||||||
|
configureGestureHandler={handler => {
|
||||||
|
if (swipeEnabled) {
|
||||||
|
if (isDrawerOpen) {
|
||||||
|
return handler.activeOffsetX([-1, 1])
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
handler
|
||||||
|
// Any movement to the left is a pager swipe
|
||||||
|
// so fail the drawer gesture immediately.
|
||||||
|
.failOffsetX(-1)
|
||||||
|
// Don't rush declaring that a movement to the right
|
||||||
|
// is a drawer swipe. It could be a vertical scroll.
|
||||||
|
.activeOffsetX(5)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fail the gesture immediately.
|
||||||
|
// This seems more reliable than the `swipeEnabled` prop.
|
||||||
|
// With `swipeEnabled` alone, the gesture may freeze after toggling off/on.
|
||||||
|
return handler.failOffsetX([0, 0]).failOffsetY([0, 0])
|
||||||
|
}
|
||||||
|
}}
|
||||||
open={isDrawerOpen}
|
open={isDrawerOpen}
|
||||||
onOpen={onOpenDrawer}
|
onOpen={onOpenDrawer}
|
||||||
onClose={onCloseDrawer}
|
onClose={onCloseDrawer}
|
||||||
swipeEdgeWidth={winDim.width / 2}
|
swipeEdgeWidth={winDim.width}
|
||||||
|
swipeMinVelocity={100}
|
||||||
|
swipeMinDistance={10}
|
||||||
drawerType={isIOS ? 'slide' : 'front'}
|
drawerType={isIOS ? 'slide' : 'front'}
|
||||||
swipeEnabled={!canGoBack && hasSession && !isDrawerSwipeDisabled}
|
|
||||||
overlayStyle={{
|
overlayStyle={{
|
||||||
backgroundColor: select(t.name, {
|
backgroundColor: select(t.name, {
|
||||||
light: 'rgba(0, 57, 117, 0.1)',
|
light: 'rgba(0, 57, 117, 0.1)',
|
||||||
|
|||||||
Reference in New Issue
Block a user