diff options
author | dan <dan.abramov@gmail.com> | 2024-12-10 04:40:40 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-10 04:40:40 +0000 |
commit | 46e1e5cee6f0670444da4e1c64a26d8247cf49ec (patch) | |
tree | 6b74644ea81733c11794796b712b5fe7ab077db5 /src/view/com/pager/Pager.tsx | |
parent | fec3352b68473f1e1d9b2c038a783b7e2c8650e6 (diff) | |
download | voidsky-46e1e5cee6f0670444da4e1c64a26d8247cf49ec.tar.zst |
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
Diffstat (limited to 'src/view/com/pager/Pager.tsx')
-rw-r--r-- | src/view/com/pager/Pager.tsx | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index da7fd1e93..2c0bbee52 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -1,5 +1,7 @@ -import React, {forwardRef} from 'react' +import React, {forwardRef, useCallback, useContext} from 'react' import {View} from 'react-native' +import {DrawerGestureContext} from 'react-native-drawer-layout' +import {Gesture, GestureDetector} from 'react-native-gesture-handler' import PagerView, { PagerViewOnPageScrollEventData, PagerViewOnPageSelectedEvent, @@ -13,7 +15,9 @@ import Animated, { useHandler, useSharedValue, } from 'react-native-reanimated' +import {useFocusEffect} from '@react-navigation/native' +import {useSetDrawerSwipeDisabled} from '#/state/shell' import {atoms as a, native} from '#/alf' export type PageSelectedEvent = PagerViewOnPageSelectedEvent @@ -58,6 +62,18 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( const [selectedPage, setSelectedPage] = React.useState(initialPage) 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, () => ({ setPage: (index: number) => { pagerView.current?.setPage(index) @@ -96,6 +112,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( }, onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) { 'worklet' + runOnJS(setIsIdle)(e.pageScrollState === 'idle') if (dragState.get() === 'idle' && e.pageScrollState === 'settling') { // This is a programmatic scroll on Android. // Stay "idle" to match iOS and avoid confusing downstream code. @@ -113,6 +130,10 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( [parentOnPageScrollStateChanged], ) + const drawerGesture = useContext(DrawerGestureContext)! + const nativeGesture = + Gesture.Native().requireExternalGestureToFail(drawerGesture) + return ( <View testID={testID} style={[a.flex_1, native(a.overflow_hidden)]}> {renderTabBar({ @@ -121,13 +142,15 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( dragProgress, dragState, })} - <AnimatedPagerView - ref={pagerView} - style={[a.flex_1]} - initialPage={initialPage} - onPageScroll={handlePageScroll}> - {children} - </AnimatedPagerView> + <GestureDetector gesture={nativeGesture}> + <AnimatedPagerView + ref={pagerView} + style={[a.flex_1]} + initialPage={initialPage} + onPageScroll={handlePageScroll}> + {children} + </AnimatedPagerView> + </GestureDetector> </View> ) }, |