react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
86 lines (82 loc) • 3.05 kB
JavaScript
;
import { use, useCallback, useEffect, useRef, useState } from 'react';
import { Worklets } from '../../handlers/gestures/reanimatedWrapper';
import { JSResponderContext, updateResponderEventValue } from '../scrollViewInterop';
import { SingleGestureName } from '../types';
import { isComposedGesture, isGestureEnabled } from './utils';
import { getEnabledSharedValues, SHARED_VALUE_OFFSET } from './utils/reanimatedUtils';
// adding 0.5 to not call Math.random and to make sure that listener ID is not an integer to avoid conflicts
let nextJSResponderContextListenerId = SHARED_VALUE_OFFSET + 0.5;
function isSupportedGesture(gesture) {
if (isComposedGesture(gesture)) {
return gesture.gestures.some(isSupportedGesture);
}
switch (gesture.type) {
case SingleGestureName.Tap:
case SingleGestureName.LongPress:
case SingleGestureName.Fling:
case SingleGestureName.Native:
case SingleGestureName.Hover:
return true;
default:
return false;
}
}
export function useJSResponderHandler(gesture) {
const jsResponderContext = use(JSResponderContext);
const [enabledSharedValueRevision, setEnabledSharedValueRevision] = useState(0);
const listenerIdRef = useRef(null);
if (listenerIdRef.current === null) {
listenerIdRef.current = nextJSResponderContextListenerId++;
}
useEffect(() => {
const enabledSharedValues = getEnabledSharedValues(gesture);
if (Worklets === undefined || enabledSharedValues.length === 0) {
return;
}
const listenerId = listenerIdRef.current;
if (listenerId === null) {
return;
}
const {
scheduleOnUI,
scheduleOnRN
} = Worklets;
const notifyEnabledChanged = () => {
setEnabledSharedValueRevision(revision => revision + 1);
};
const attachListeners = (sharedValues, id, notify) => {
'worklet';
const listener = () => {
scheduleOnRN(notify);
};
for (const sharedValue of sharedValues) {
sharedValue.addListener(id, listener);
}
};
const detachListeners = (sharedValues, id) => {
'worklet';
for (const sharedValue of sharedValues) {
sharedValue.removeListener(id);
}
};
scheduleOnUI(attachListeners, enabledSharedValues, listenerId, notifyEnabledChanged);
return () => {
scheduleOnUI(detachListeners, enabledSharedValues, listenerId);
};
}, [gesture]);
const shouldHandleJSResponderEvent = useCallback(() => {
void enabledSharedValueRevision;
return isGestureEnabled(gesture) && isSupportedGesture(gesture);
}, [enabledSharedValueRevision, gesture]);
const handleStartShouldSetResponder = useCallback(() => {
if (shouldHandleJSResponderEvent()) {
updateResponderEventValue(jsResponderContext, true);
}
return false;
}, [jsResponderContext, shouldHandleJSResponderEvent]);
return {
handleStartShouldSetResponder: jsResponderContext == null ? () => false : handleStartShouldSetResponder
};
}
//# sourceMappingURL=useJSResponderHandler.js.map