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 @@ -31,6 +31,10 @@ class NativeViewGestureHandler : GestureHandler() {

private var hook: NativeViewGestureHandlerHook = defaultHook

private data class ActiveUpdateSnapshot(val pointerInside: Boolean, val numberOfPointers: Int, val pointerType: Int)

private var lastActiveUpdate: ActiveUpdateSnapshot? = null

init {
shouldCancelWhenOutside = true
}
Expand Down Expand Up @@ -163,6 +167,21 @@ class NativeViewGestureHandler : GestureHandler() {

override fun onReset() {
this.hook = defaultHook
lastActiveUpdate = null
}

override fun dispatchHandlerUpdate(event: MotionEvent) {
val snapshot = ActiveUpdateSnapshot(isWithinBounds, numberOfPointers, pointerType)
if (snapshot == lastActiveUpdate) {
return
}
lastActiveUpdate = snapshot
super.dispatchHandlerUpdate(event)
}

override fun dispatchStateChange(newState: Int, prevState: Int) {
lastActiveUpdate = null
super.dispatchStateChange(newState, prevState)
}

override fun wantsToAttachDirectlyToView() = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ - (void)updateStateIfScrollView
@implementation RNNativeViewGestureHandler {
BOOL _shouldActivateOnStart;
BOOL _disallowInterruption;
RNGestureHandlerEventExtraData *_lastActiveExtraData;
}

- (instancetype)initWithTag:(NSNumber *)tag
Expand Down Expand Up @@ -180,6 +181,16 @@ - (void)unbindFromView
[super unbindFromView];
}

- (void)sendActiveStateEventIfChangedForView:(UIView *)sender extraData:(RNGestureHandlerEventExtraData *)extraData
{
if ([_lastActiveExtraData.data isEqualToDictionary:extraData.data]) {
return;
}

_lastActiveExtraData = extraData;
[self sendEventsInState:RNGestureHandlerStateActive forViewWithTag:sender.reactTag withExtraData:extraData];
}

- (void)handleTouchDown:(UIView *)sender forEvent:(UIEvent *)event
{
[self setCurrentPointerTypeForEvent:event];
Expand All @@ -202,11 +213,11 @@ - (void)handleTouchDown:(UIView *)sender forEvent:(UIEvent *)event
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];

[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
_lastActiveExtraData = nil;
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
Comment thread
m-bert marked this conversation as resolved.
withPointerType:_pointerType]];
}

- (void)handleTouchUpOutside:(UIView *)sender forEvent:(UIEvent *)event
Expand Down Expand Up @@ -238,30 +249,27 @@ - (void)handleDragExit:(UIView *)sender forEvent:(UIEvent *)event
UIControl *control = (UIControl *)sender;
[control cancelTrackingWithEvent:event];
} else {
[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
}
}

- (void)handleDragEnter:(UIView *)sender forEvent:(UIEvent *)event
{
[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
}

- (void)handleDragInside:(UIView *)sender forEvent:(UIEvent *)event
{
[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
}

- (void)handleDragOutside:(UIView *)sender forEvent:(UIEvent *)event
Expand All @@ -270,11 +278,10 @@ - (void)handleDragOutside:(UIView *)sender forEvent:(UIEvent *)event
return;
}

[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
}

- (void)handleTouchCancel:(UIView *)sender forEvent:(UIEvent *)event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { tagMessage } from '../../utils';
import type {
GestureStateChangeEventWithHandlerData,
GestureUpdateEventWithHandlerData,
HandlerData,
SingleGestureName,
} from '../../v3/types';
import type {
Expand Down Expand Up @@ -430,19 +431,21 @@ export default abstract class GestureHandler implements IGestureHandler {
onGestureHandlerReanimatedStateChange,
}: PropsRef = this.propsRef!.current;

const isStateChange = this.lastSentState !== newState;

const resultEvent: ResultEvent = !usesNativeOrVirtualDetector(
this.actionType
)
? this.transformEventData(newState, oldState)
: this.lastSentState !== newState
: isStateChange
? this.transformStateChangeEvent(newState, oldState)
: this.transformUpdateEvent(newState);

// In the v2 API oldState field has to be undefined, unless we send event state changed
// Here the order is flipped to avoid workarounds such as making backup of the state and setting it to undefined first, then changing it back
// Flipping order with setting oldState to undefined solves issue, when events were being sent twice instead of once
// However, this may cause trouble in the future (but for now we don't know that)
if (this.lastSentState !== newState) {
if (isStateChange) {
this.lastSentState = newState;

if (this.forReanimated) {
Expand All @@ -456,6 +459,16 @@ export default abstract class GestureHandler implements IGestureHandler {
return;
}

// Cover only V3 path due to different event shape
if (!isStateChange && usesNativeOrVirtualDetector(this.actionType)) {
const handlerData = (
resultEvent.nativeEvent as GestureUpdateEventWithHandlerData<unknown>
).handlerData;
if (this.shouldSuppressActiveUpdate(handlerData)) {
return;
}
}

(resultEvent.nativeEvent as GestureHandlerNativeEvent).oldState = undefined;

if (this.forReanimated) {
Expand All @@ -467,6 +480,12 @@ export default abstract class GestureHandler implements IGestureHandler {
}
};

protected shouldSuppressActiveUpdate(
_handlerData: HandlerData<unknown>
): boolean {
return false;
}

private transformEventData(
newState: State,
oldState: State
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { Platform } from 'react-native';

import type { ActionType } from '../../ActionType';
import { State } from '../../State';
import { deepEqual } from '../../utils';
import type { NativeHandlerData } from '../../v3/hooks/gestures/native/NativeTypes';
import type { HandlerData } from '../../v3/types';
import { SingleGestureName } from '../../v3/types';
import { DEFAULT_TOUCH_SLOP } from '../constants';
import type { AdaptedEvent, Config, PropsRef } from '../interfaces';
import type { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
import GestureHandler from './GestureHandler';
import type IGestureHandler from './IGestureHandler';

export default class NativeViewGestureHandler extends GestureHandler {
private buttonRole!: boolean;

Expand All @@ -20,6 +24,8 @@ export default class NativeViewGestureHandler extends GestureHandler {
private startY = 0;
private minDistSq = DEFAULT_TOUCH_SLOP * DEFAULT_TOUCH_SLOP;

private lastActiveHandlerData: HandlerData<NativeHandlerData> | null = null;

public constructor(
delegate: GestureHandlerDelegate<unknown, IGestureHandler>
) {
Expand Down Expand Up @@ -199,4 +205,22 @@ export default class NativeViewGestureHandler extends GestureHandler {
),
};
}

protected override shouldSuppressActiveUpdate(
handlerData: HandlerData<NativeHandlerData>
): boolean {
if (
this.lastActiveHandlerData &&
deepEqual(this.lastActiveHandlerData, handlerData)
) {
return true;
}
this.lastActiveHandlerData = handlerData;
return false;
}

public override reset(): void {
super.reset();
this.lastActiveHandlerData = null;
}
}
Loading