mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-12 05:10:52 +02:00
fix pull search gesture despawn bug
This commit is contained in:
@@ -28,7 +28,6 @@ import {
|
|||||||
} from 'react-native-gesture-handler';
|
} from 'react-native-gesture-handler';
|
||||||
import {
|
import {
|
||||||
runOnJS,
|
runOnJS,
|
||||||
runOnUI,
|
|
||||||
useSharedValue
|
useSharedValue
|
||||||
} from 'react-native-reanimated';
|
} from 'react-native-reanimated';
|
||||||
import { Text } from '@/components/Text';
|
import { Text } from '@/components/Text';
|
||||||
@@ -44,11 +43,11 @@ const RESET_THRESHOLD = 58;
|
|||||||
const MAX_PULL = 112;
|
const MAX_PULL = 112;
|
||||||
|
|
||||||
type PullSearchGestureRef = MutableRefObject<GestureType | undefined>;
|
type PullSearchGestureRef = MutableRefObject<GestureType | undefined>;
|
||||||
type SimultaneousHandlers = NativeViewGestureHandlerProps['simultaneousHandlers'];
|
type WaitForHandlers = NativeViewGestureHandlerProps['waitFor'];
|
||||||
type PullSearchScrollViewProps = ScrollViewProps & Pick<NativeViewGestureHandlerProps, 'simultaneousHandlers'>;
|
type PullSearchScrollViewProps = ScrollViewProps &
|
||||||
|
Pick<NativeViewGestureHandlerProps, 'simultaneousHandlers' | 'waitFor'>;
|
||||||
type PullSearchContextValue = {
|
type PullSearchContextValue = {
|
||||||
gestureRef: PullSearchGestureRef;
|
gestureRef: PullSearchGestureRef;
|
||||||
cancelIfScrolledAway: (offsetY: number) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const PullSearchGestureContext = createContext<PullSearchContextValue | null>(null);
|
const PullSearchGestureContext = createContext<PullSearchContextValue | null>(null);
|
||||||
@@ -57,10 +56,10 @@ function clamp(value: number, min: number, max: number): number {
|
|||||||
return Math.max(min, Math.min(max, value));
|
return Math.max(min, Math.min(max, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeSimultaneousHandlers(
|
function mergeWaitForHandlers(
|
||||||
existing: SimultaneousHandlers,
|
existing: WaitForHandlers,
|
||||||
contextValue: PullSearchContextValue | null
|
contextValue: PullSearchContextValue | null
|
||||||
): SimultaneousHandlers {
|
): WaitForHandlers {
|
||||||
if (!contextValue) return existing;
|
if (!contextValue) return existing;
|
||||||
if (!existing) return contextValue.gestureRef;
|
if (!existing) return contextValue.gestureRef;
|
||||||
return Array.isArray(existing)
|
return Array.isArray(existing)
|
||||||
@@ -69,26 +68,18 @@ function mergeSimultaneousHandlers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PullSearchScrollView = forwardRef<RNScrollView, PullSearchScrollViewProps>(
|
export const PullSearchScrollView = forwardRef<RNScrollView, PullSearchScrollViewProps>(
|
||||||
function PullSearchScrollView({ simultaneousHandlers, onScroll, ...props }, ref) {
|
function PullSearchScrollView({ waitFor, ...props }, ref) {
|
||||||
const pullSearchContext = useContext(PullSearchGestureContext);
|
const pullSearchContext = useContext(PullSearchGestureContext);
|
||||||
const mergedHandlers = useMemo(
|
const mergedWaitFor = useMemo(
|
||||||
() => mergeSimultaneousHandlers(simultaneousHandlers, pullSearchContext),
|
() => mergeWaitForHandlers(waitFor, pullSearchContext),
|
||||||
[pullSearchContext, simultaneousHandlers]
|
[pullSearchContext, waitFor]
|
||||||
);
|
|
||||||
const handleScroll = useCallback(
|
|
||||||
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
||||||
onScroll?.(event);
|
|
||||||
pullSearchContext?.cancelIfScrolledAway(event.nativeEvent.contentOffset.y);
|
|
||||||
},
|
|
||||||
[onScroll, pullSearchContext]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GestureScrollView
|
<GestureScrollView
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
onScroll={handleScroll}
|
waitFor={mergedWaitFor}
|
||||||
simultaneousHandlers={mergedHandlers}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -142,6 +133,7 @@ export function PullSearchGesture({
|
|||||||
const pullValue = useSharedValue(0);
|
const pullValue = useSharedValue(0);
|
||||||
const armedValue = useSharedValue(false);
|
const armedValue = useSharedValue(false);
|
||||||
const draggingValue = useSharedValue(false);
|
const draggingValue = useSharedValue(false);
|
||||||
|
const pullOriginY = useSharedValue(0);
|
||||||
|
|
||||||
const resetUi = useCallback(() => {
|
const resetUi = useCallback(() => {
|
||||||
setArmed(false);
|
setArmed(false);
|
||||||
@@ -155,27 +147,9 @@ export function PullSearchGesture({
|
|||||||
resetUi();
|
resetUi();
|
||||||
}, [onOpen, resetUi]);
|
}, [onOpen, resetUi]);
|
||||||
|
|
||||||
const resetShared = useCallback(() => {
|
|
||||||
runOnUI(() => {
|
|
||||||
'worklet';
|
|
||||||
pullValue.value = 0;
|
|
||||||
armedValue.value = false;
|
|
||||||
draggingValue.value = false;
|
|
||||||
})();
|
|
||||||
}, [armedValue, draggingValue, pullValue]);
|
|
||||||
|
|
||||||
const cancelIfScrolledAway = useCallback(
|
|
||||||
(offsetY: number) => {
|
|
||||||
if (offsetY <= 2 || !dragging) return;
|
|
||||||
resetShared();
|
|
||||||
resetUi();
|
|
||||||
},
|
|
||||||
[dragging, resetShared, resetUi]
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextValue = useMemo<PullSearchContextValue>(
|
const contextValue = useMemo<PullSearchContextValue>(
|
||||||
() => ({ gestureRef: pullGestureRef, cancelIfScrolledAway }),
|
() => ({ gestureRef: pullGestureRef }),
|
||||||
[cancelIfScrolledAway, pullGestureRef]
|
[pullGestureRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const pullGesture = useMemo(
|
const pullGesture = useMemo(
|
||||||
@@ -186,6 +160,19 @@ export function PullSearchGesture({
|
|||||||
.activeOffsetY(10)
|
.activeOffsetY(10)
|
||||||
.failOffsetY(-8)
|
.failOffsetY(-8)
|
||||||
.failOffsetX([-28, 28])
|
.failOffsetX([-28, 28])
|
||||||
|
.onTouchesDown((event) => {
|
||||||
|
'worklet';
|
||||||
|
if (event.numberOfTouches !== 1) return;
|
||||||
|
pullOriginY.value = event.allTouches[0]?.absoluteY ?? 0;
|
||||||
|
})
|
||||||
|
.onTouchesMove((event, stateManager) => {
|
||||||
|
'worklet';
|
||||||
|
if (!draggingValue.value || event.numberOfTouches !== 1) return;
|
||||||
|
const touchY = event.allTouches[0]?.absoluteY;
|
||||||
|
if (touchY !== undefined && touchY <= pullOriginY.value) {
|
||||||
|
stateManager.fail();
|
||||||
|
}
|
||||||
|
})
|
||||||
.onStart(() => {
|
.onStart(() => {
|
||||||
'worklet';
|
'worklet';
|
||||||
pullValue.value = 0;
|
pullValue.value = 0;
|
||||||
@@ -211,8 +198,9 @@ export function PullSearchGesture({
|
|||||||
runOnJS(playHaptic)('thresholdExit');
|
runOnJS(playHaptic)('thresholdExit');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onEnd((event) => {
|
.onEnd((event, success) => {
|
||||||
'worklet';
|
'worklet';
|
||||||
|
if (!success) return;
|
||||||
const finalPull = pullValue.value;
|
const finalPull = pullValue.value;
|
||||||
pullValue.value = 0;
|
pullValue.value = 0;
|
||||||
armedValue.value = false;
|
armedValue.value = false;
|
||||||
@@ -239,6 +227,7 @@ export function PullSearchGesture({
|
|||||||
enabled,
|
enabled,
|
||||||
open,
|
open,
|
||||||
pullGestureRef,
|
pullGestureRef,
|
||||||
|
pullOriginY,
|
||||||
pullValue,
|
pullValue,
|
||||||
resetUi,
|
resetUi,
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user