Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -902,8 +902,8 @@ open class GestureHandler {
if (config.hasKey(KEY_DISPATCHES_ANIMATED_EVENTS)) {
handler.dispatchesAnimatedEvents = config.getBoolean(KEY_DISPATCHES_ANIMATED_EVENTS)
}
if (config.hasKey(KEY_SHOULD_USE_REANIMATED)) {
handler.dispatchesReanimatedEvents = config.getBoolean(KEY_SHOULD_USE_REANIMATED)
if (config.hasKey(KEY_DISPATCHES_REANIMATED_EVENTS)) {
handler.dispatchesReanimatedEvents = config.getBoolean(KEY_DISPATCHES_REANIMATED_EVENTS)
Comment thread
j-piasecki marked this conversation as resolved.
}
if (config.hasKey(KEY_MANUAL_ACTIVATION)) {
handler.manualActivation = config.getBoolean(KEY_MANUAL_ACTIVATION)
Expand All @@ -920,7 +920,7 @@ open class GestureHandler {
private const val KEY_ENABLED = "enabled"
private const val KEY_NEEDS_POINTER_DATA = "needsPointerData"
private const val KEY_DISPATCHES_ANIMATED_EVENTS = "dispatchesAnimatedEvents"
private const val KEY_SHOULD_USE_REANIMATED = "shouldUseReanimated"
private const val KEY_DISPATCHES_REANIMATED_EVENTS = "dispatchesReanimatedEvents"
private const val KEY_MANUAL_ACTIVATION = "manualActivation"
private const val KEY_MOUSE_BUTTON = "mouseButton"
private const val KEY_HIT_SLOP = "hitSlop"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ - (void)updateConfig:(NSDictionary *)config
_dispatchesAnimatedEvents = [RCTConvert BOOL:prop];
}

prop = config[@"shouldUseReanimated"];
prop = config[@"dispatchesReanimatedEvents"];
Comment thread
j-piasecki marked this conversation as resolved.
if (prop != nil) {
_dispatchesReanimatedEvents = [RCTConvert BOOL:prop];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function NativeDetector<THandlerData, TConfig>({

const NativeDetectorComponent = gesture.config.dispatchesAnimatedEvents
? AnimatedNativeDetector
: gesture.config.shouldUseReanimated
: gesture.config.shouldUseReanimatedDetector
? ReanimatedNativeDetector
: HostGestureDetector;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ComposedGesture,
ComposedGestureName,
AnyGesture,
ComposedGestureConfig,
} from '../../types';
import { tagMessage } from '../../../utils';
import { Reanimated } from '../../../handlers/gestures/reanimatedWrapper';
Expand All @@ -27,16 +28,16 @@ export function useComposedGesture(
);
}

const config = {
shouldUseReanimated: gestures.some(
(gesture) => gesture.config.shouldUseReanimated
const config: ComposedGestureConfig = {
shouldUseReanimatedDetector: gestures.some(
(gesture) => gesture.config.shouldUseReanimatedDetector
),
dispatchesAnimatedEvents: gestures.some(
(gesture) => gesture.config.dispatchesAnimatedEvents
),
};

if (config.shouldUseReanimated && config.dispatchesAnimatedEvents) {
if (config.shouldUseReanimatedDetector && config.dispatchesAnimatedEvents) {
throw new Error(
tagMessage(
'Composed gestures cannot use both Reanimated and Animated events at the same time.'
Expand Down
20 changes: 6 additions & 14 deletions packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ import { useEffect, useMemo } from 'react';
import { getNextHandlerTag } from '../../handlers/getNextHandlerTag';
import RNGestureHandlerModule from '../../RNGestureHandlerModule';
import { useGestureCallbacks } from './useGestureCallbacks';
import { Reanimated } from '../../handlers/gestures/reanimatedWrapper';
import {
prepareConfig,
isAnimatedEvent,
shouldHandleTouchEvents,
prepareRelations,
bindSharedValues,
hasWorkletEventHandlers,
unbindSharedValues,
prepareConfigForNativeSide,
} from './utils';
import { tagMessage } from '../../utils';
import { BaseGestureConfig, SingleGesture, SingleGestureName } from '../types';
Expand All @@ -30,15 +27,10 @@ export function useGesture<THandlerData, TConfig>(
);
}

// This has to be done ASAP as other hooks depend `shouldUseReanimated`.
config.shouldUseReanimated =
!config.disableReanimated &&
Reanimated !== undefined &&
hasWorkletEventHandlers(config);
config.needsPointerData = shouldHandleTouchEvents(config);
config.dispatchesAnimatedEvents = isAnimatedEvent(config.onUpdate);
// This has to be done ASAP as other hooks depend `shouldUseReanimatedDetector`.
prepareConfig(config);

if (config.dispatchesAnimatedEvents && config.shouldUseReanimated) {
if (config.dispatchesAnimatedEvents && config.shouldUseReanimatedDetector) {
throw new Error(
tagMessage(
`${type}: You cannot use Animated.Event together with callbacks running on the UI thread. Either remove Animated.Event from onUpdate, or set runOnJS property to true on the gesture.`
Expand Down Expand Up @@ -69,7 +61,7 @@ export function useGesture<THandlerData, TConfig>(
}

if (
config.shouldUseReanimated &&
config.shouldUseReanimatedDetector &&
(!onReanimatedStateChange ||
!onReanimatedUpdateEvent ||
!onReanimatedTouchEvent)
Expand All @@ -92,7 +84,7 @@ export function useGesture<THandlerData, TConfig>(
}, [type, tag]);

useEffect(() => {
const preparedConfig = prepareConfig(type, config);
const preparedConfig = prepareConfigForNativeSide(type, config);
RNGestureHandlerModule.setGestureHandlerConfig(tag, preparedConfig);
RNGestureHandlerModule.flushOperations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,34 @@ import { Reanimated } from '../../../handlers/gestures/reanimatedWrapper';
import { tagMessage } from '../../../utils';
import {
BaseGestureConfig,
CommonGestureConfig,
ExcludeInternalConfigProps,
GestureCallbacks,
HandlersPropsWhiteList,
InternalConfigProps,
SingleGestureName,
} from '../../types';
import { PanNativeProperties } from '../gestures/pan/PanProperties';
import { FlingNativeProperties } from '../gestures/fling/FlingProperties';
import { HoverNativeProperties } from '../gestures/hover/HoverProperties';
import { LongPressNativeProperties } from '../gestures/longPress/LongPressProperties';
import { NativeHandlerNativeProperties } from '../gestures/native/NativeProperties';
import { TapNativeProperties } from '../gestures/tap/TapProperties';

const allowedNativeProps = new Set<
keyof CommonGestureConfig | keyof InternalConfigProps<unknown>
>([
// CommonGestureConfig
'disableReanimated',
'enabled',
'shouldCancelWhenOutside',
'hitSlop',
'userSelect',
'activeCursor',
'mouseButton',
'enableContextMenu',
'touchAction',

// InternalConfigProps
'shouldUseReanimated',
'dispatchesAnimatedEvents',
'needsPointerData',
'changeEventCalculator',
]);

export const HandlerCallbacks = new Set<
keyof Required<GestureCallbacks<unknown>>
>([
'onBegin',
'onStart',
'onUpdate',
'onEnd',
'onFinalize',
'onTouchesDown',
'onTouchesMove',
'onTouchesUp',
'onTouchesCancelled',
]);

const PropsToFilter = new Set<BaseGestureConfig<unknown, unknown>>([
...HandlerCallbacks,

// Config props
'changeEventCalculator',
'disableReanimated',

// Relations
'simultaneousWithExternalGesture',
'requireExternalGestureToFail',
'blocksExternalGesture',
]);

export const PropsWhiteLists = new Map<
SingleGestureName,
HandlersPropsWhiteList
>([
[SingleGestureName.Pan, PanNativeProperties],
[SingleGestureName.Tap, TapNativeProperties],
[SingleGestureName.Native, NativeHandlerNativeProperties],
[SingleGestureName.Fling, FlingNativeProperties],
[SingleGestureName.Hover, HoverNativeProperties],
[SingleGestureName.LongPress, LongPressNativeProperties],
]);

const EMPTY_WHITE_LIST = new Set<string>();
import { hasWorkletEventHandlers, maybeUnpackValue } from './reanimatedUtils';
import { isAnimatedEvent, shouldHandleTouchEvents } from './eventUtils';
import {
allowedNativeProps,
EMPTY_WHITE_LIST,
PropsToFilter,
PropsWhiteLists,
} from './propsWhiteList';

export function prepareConfig<THandlerData, TConfig extends object>(
config: BaseGestureConfig<THandlerData, TConfig>
) {
const runOnJS = maybeUnpackValue(config.runOnJS);

config.shouldUseReanimatedDetector =
!config.disableReanimated &&
Reanimated !== undefined &&
hasWorkletEventHandlers(config);
config.needsPointerData = shouldHandleTouchEvents(config);
config.dispatchesAnimatedEvents = isAnimatedEvent(config.onUpdate);
config.dispatchesReanimatedEvents =
config.shouldUseReanimatedDetector && !runOnJS;
}

export function prepareConfigForNativeSide<THandlerData, TConfig>(
handlerType: SingleGestureName,
config: BaseGestureConfig<THandlerData, TConfig>
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './eventHandlersUtils';
export * from './eventUtils';
export * from './reanimatedUtils';
export * from './relationUtils';
export * from './propsWhiteList';
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
BaseGestureConfig,
CommonGestureConfig,
GestureCallbacks,
HandlersPropsWhiteList,
InternalConfigProps,
SingleGestureName,
} from '../../types';
import { FlingNativeProperties } from '../gestures/fling/FlingProperties';
import { HoverNativeProperties } from '../gestures/hover/HoverProperties';
import { LongPressNativeProperties } from '../gestures/longPress/LongPressProperties';
import { NativeHandlerNativeProperties } from '../gestures/native/NativeProperties';
import { PanNativeProperties } from '../gestures/pan/PanProperties';
import { TapNativeProperties } from '../gestures/tap/TapProperties';

export const allowedNativeProps = new Set<
keyof CommonGestureConfig | keyof InternalConfigProps<unknown>
>([
// CommonGestureConfig
'disableReanimated',
'enabled',
'shouldCancelWhenOutside',
'hitSlop',
'userSelect',
'activeCursor',
'mouseButton',
'enableContextMenu',
'touchAction',

// InternalConfigProps
'dispatchesReanimatedEvents',
'dispatchesAnimatedEvents',
'needsPointerData',
'changeEventCalculator',
]);

export const HandlerCallbacks = new Set<
keyof Required<GestureCallbacks<unknown>>
>([
'onBegin',
'onStart',
'onUpdate',
'onEnd',
'onFinalize',
'onTouchesDown',
'onTouchesMove',
'onTouchesUp',
'onTouchesCancelled',
]);

export const PropsToFilter = new Set<BaseGestureConfig<unknown, unknown>>([
...HandlerCallbacks,

// Config props
'changeEventCalculator',
'disableReanimated',

// Relations
'simultaneousWithExternalGesture',
'requireExternalGestureToFail',
'blocksExternalGesture',
]);

export const PropsWhiteLists = new Map<
SingleGestureName,
HandlersPropsWhiteList
>([
[SingleGestureName.Pan, PanNativeProperties],
[SingleGestureName.Tap, TapNativeProperties],
[SingleGestureName.Native, NativeHandlerNativeProperties],
[SingleGestureName.Fling, FlingNativeProperties],
[SingleGestureName.Hover, HoverNativeProperties],
[SingleGestureName.LongPress, LongPressNativeProperties],
]);

export const EMPTY_WHITE_LIST = new Set<string>();
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import RNGestureHandlerModule from '../../../RNGestureHandlerModule';
import { Reanimated } from '../../../handlers/gestures/reanimatedWrapper';
import { BaseGestureConfig, SharedValue, SharedValueOrT } from '../../types';
import { HandlerCallbacks } from './configUtils';
import { HandlerCallbacks } from './propsWhiteList';

// Variant of djb2 hash function.
// Taken from https://gist.github.com/eplawless/52813b1d8ad9af510d85?permalink_comment_id=3367765#gistcomment-3367765
Expand Down Expand Up @@ -37,7 +37,16 @@ export function bindSharedValues<THandlerData, TConfig>(
const listenerId = baseListenerId + keyHash;

sharedValue.addListener(listenerId, (value) => {
updateGestureHandlerConfig(handlerTag, { [configKey]: value });
if (configKey === 'runOnJS') {
config.dispatchesReanimatedEvents =
Comment thread
j-piasecki marked this conversation as resolved.
config.shouldUseReanimatedDetector && !value;
Comment thread
j-piasecki marked this conversation as resolved.

updateGestureHandlerConfig(handlerTag, {
dispatchesReanimatedEvents: config.dispatchesReanimatedEvents,
});
} else {
updateGestureHandlerConfig(handlerTag, { [configKey]: value });
}
flushOperations();
});
};
Expand Down
19 changes: 12 additions & 7 deletions packages/react-native-gesture-handler/src/v3/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,15 @@ export type SingleGesture<THandlerData, TConfig> = {
gestureRelations: GestureRelations;
};

export type ComposedGestureConfig = {
shouldUseReanimatedDetector: boolean;
dispatchesAnimatedEvents: boolean;
};

export type ComposedGesture = {
tags: number[];
type: ComposedGestureName;
config: {
shouldUseReanimated: boolean;
dispatchesAnimatedEvents: boolean;
};
config: ComposedGestureConfig;
gestureEvents: GestureEvents<unknown>;
externalSimultaneousHandlers: number[];
gestures: Gesture[];
Expand Down Expand Up @@ -176,15 +178,18 @@ export interface GestureCallbacks<THandlerData> {
}

export type InternalConfigProps<THandlerData> = {
shouldUseReanimated?: boolean;
shouldUseReanimatedDetector?: boolean;
dispatchesReanimatedEvents?: boolean;
dispatchesAnimatedEvents?: boolean;
needsPointerData?: boolean;
changeEventCalculator?: ChangeCalculatorType<THandlerData>;
};

export type CommonGestureConfig = WithSharedValue<
export type CommonGestureConfig = {
disableReanimated?: boolean;
} & WithSharedValue<
{
disableReanimated?: boolean;
runOnJS?: boolean;
enabled?: boolean;
shouldCancelWhenOutside?: boolean;
hitSlop?: HitSlop;
Expand Down
Loading