From 14e7ac06afc2b31853e3660649f1d6063722689d Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Wed, 10 Jan 2024 17:21:54 +0100 Subject: [PATCH] Fix double start when `activateAfterLongPress` is used (#2628) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description It seems like native iOS recognizers (or at least Pan) don't respect when their state is changed from outside, which caused a problem with `.activateAfterLongPress` - before sending event in `Active` state, the state of the native recognizer is updated to `UIGestureRecognizerStateBegan`. Despite this, after moving the finger it tries to change the state to `UIGestureRecognizerStateBegan` once more, causing weird `Active` -> `Began`, `Began` -> `Active` chain. This PR adds a simple check to detect the first event and stop processing in case it happens. ~~One thing that *could* be related is the fact that when the gesture fails before activation, the gesture stays in the `Began` state until the finger is lifted. This still needs to be investigated.~~ I think this is a separate issue. Fixes https://github.com/software-mansion/react-native-gesture-handler/issues/2620 ## Test plan Tested on the example app. --------- Co-authored-by: MichaƂ Bert <63123542+m-bert@users.noreply.github.com> --- apple/RNGestureHandler.m | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apple/RNGestureHandler.m b/apple/RNGestureHandler.m index 4ff64d9616..07e56c1359 100644 --- a/apple/RNGestureHandler.m +++ b/apple/RNGestureHandler.m @@ -240,6 +240,15 @@ - (void)sendEventsInState:(RNGestureHandlerState)state return; } + // Recognizers don't respect manually changing their state (that happens when we are activating handler + // under custom conditions). If we send a custom event in state ACTIVE and the recognizer will later update its + // state, we will end up sending ACTIVE->BEGAN and BEGAN->ACTIVE chain. To prevent this, we simply detect the first + // weird state change and stop it (then we don't update _lastState), so the second call ends up without state change + // and is fine. + if (state == RNGestureHandlerStateBegan && _lastState == RNGestureHandlerStateActive) { + return; + } + if (state == RNGestureHandlerStateActive) { // Generate a unique coalescing-key each time the gesture-handler becomes active. All events will have // the same coalescing-key allowing RCTEventDispatcher to coalesce RNGestureHandlerEvents when events are