react-native-gesture-handler 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +3 -2
  2. package/android/build.gradle +28 -4
  3. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +9 -5
  4. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt +6 -1
  5. package/android/lib/src/main/java/com/swmansion/gesturehandler/NativeViewGestureHandler.kt +103 -22
  6. package/android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.kt +29 -2
  7. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +74 -84
  8. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +4 -0
  9. package/android/src/main/jni/Android.mk +1 -2
  10. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +12 -9
  11. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerInterface.java +1 -0
  12. package/ios/Handlers/RNFlingHandler.m +43 -1
  13. package/ios/Handlers/{RNNativeViewHandler.m → RNNativeViewHandler.mm} +13 -1
  14. package/ios/Handlers/RNPanHandler.m +27 -0
  15. package/ios/RNGestureHandler.h +1 -0
  16. package/ios/RNGestureHandler.m +22 -4
  17. package/ios/RNGestureHandlerManager.mm +10 -2
  18. package/ios/RNGestureHandlerModule.mm +4 -1
  19. package/ios/RNManualActivationRecognizer.m +10 -3
  20. package/ios/RNRootViewGestureRecognizer.m +12 -1
  21. package/lib/commonjs/RNGestureHandlerModule.macos.js +81 -0
  22. package/lib/commonjs/RNGestureHandlerModule.macos.js.map +1 -0
  23. package/lib/commonjs/components/DrawerLayout.js +38 -11
  24. package/lib/commonjs/components/DrawerLayout.js.map +1 -1
  25. package/lib/commonjs/components/GestureButtons.js.map +1 -1
  26. package/lib/commonjs/components/touchables/GenericTouchable.js +4 -1
  27. package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
  28. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  29. package/lib/commonjs/handlers/ForceTouchGestureHandler.js +2 -1
  30. package/lib/commonjs/handlers/ForceTouchGestureHandler.js.map +1 -1
  31. package/lib/commonjs/handlers/PanGestureHandler.js +1 -1
  32. package/lib/commonjs/handlers/PanGestureHandler.js.map +1 -1
  33. package/lib/commonjs/handlers/PressabilityDebugView.js +14 -0
  34. package/lib/commonjs/handlers/PressabilityDebugView.js.map +1 -0
  35. package/lib/commonjs/handlers/PressabilityDebugView.web.js +12 -0
  36. package/lib/commonjs/handlers/PressabilityDebugView.web.js.map +1 -0
  37. package/lib/commonjs/handlers/createHandler.js +25 -11
  38. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  39. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  40. package/lib/commonjs/handlers/gestures/GestureDetector.js +83 -63
  41. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  42. package/lib/commonjs/handlers/gestures/gesture.js +13 -2
  43. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  44. package/lib/commonjs/handlers/gestures/gestureStateManager.js +13 -9
  45. package/lib/commonjs/handlers/gestures/gestureStateManager.js.map +1 -1
  46. package/lib/commonjs/handlers/gestures/panGesture.js +5 -0
  47. package/lib/commonjs/handlers/gestures/panGesture.js.map +1 -1
  48. package/lib/commonjs/mocks.js +2 -0
  49. package/lib/commonjs/mocks.js.map +1 -1
  50. package/lib/commonjs/utils.js +6 -3
  51. package/lib/commonjs/utils.js.map +1 -1
  52. package/lib/commonjs/web/utils.js.map +1 -1
  53. package/lib/module/RNGestureHandlerModule.macos.js +57 -0
  54. package/lib/module/RNGestureHandlerModule.macos.js.map +1 -0
  55. package/lib/module/components/DrawerLayout.js +38 -11
  56. package/lib/module/components/DrawerLayout.js.map +1 -1
  57. package/lib/module/components/GestureButtons.js.map +1 -1
  58. package/lib/module/components/touchables/GenericTouchable.js +4 -1
  59. package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
  60. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  61. package/lib/module/handlers/ForceTouchGestureHandler.js +1 -1
  62. package/lib/module/handlers/ForceTouchGestureHandler.js.map +1 -1
  63. package/lib/module/handlers/PanGestureHandler.js +1 -1
  64. package/lib/module/handlers/PanGestureHandler.js.map +1 -1
  65. package/lib/module/handlers/PressabilityDebugView.js +3 -0
  66. package/lib/module/handlers/PressabilityDebugView.js.map +1 -0
  67. package/lib/module/handlers/PressabilityDebugView.web.js +5 -0
  68. package/lib/module/handlers/PressabilityDebugView.web.js.map +1 -0
  69. package/lib/module/handlers/createHandler.js +26 -12
  70. package/lib/module/handlers/createHandler.js.map +1 -1
  71. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  72. package/lib/module/handlers/gestures/GestureDetector.js +83 -63
  73. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  74. package/lib/module/handlers/gestures/gesture.js +13 -2
  75. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  76. package/lib/module/handlers/gestures/gestureStateManager.js +13 -9
  77. package/lib/module/handlers/gestures/gestureStateManager.js.map +1 -1
  78. package/lib/module/handlers/gestures/panGesture.js +5 -0
  79. package/lib/module/handlers/gestures/panGesture.js.map +1 -1
  80. package/lib/module/mocks.js +2 -0
  81. package/lib/module/mocks.js.map +1 -1
  82. package/lib/module/utils.js +2 -1
  83. package/lib/module/utils.js.map +1 -1
  84. package/lib/module/web/utils.js.map +1 -1
  85. package/lib/typescript/RNGestureHandlerModule.macos.d.ts +34 -0
  86. package/lib/typescript/RNGestureHandlerModule.web.d.ts +1 -1
  87. package/lib/typescript/components/DrawerLayout.d.ts +3 -0
  88. package/lib/typescript/components/GestureButtons.d.ts +6 -0
  89. package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +1 -0
  90. package/lib/typescript/handlers/ForceTouchGestureHandler.d.ts +2 -2
  91. package/lib/typescript/handlers/PanGestureHandler.d.ts +2 -1
  92. package/lib/typescript/handlers/PressabilityDebugView.d.ts +1 -0
  93. package/lib/typescript/handlers/PressabilityDebugView.web.d.ts +1 -0
  94. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +1 -0
  95. package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -1
  96. package/lib/typescript/handlers/gestures/gesture.d.ts +3 -0
  97. package/lib/typescript/handlers/gestures/panGesture.d.ts +1 -0
  98. package/lib/typescript/mocks.d.ts +1 -0
  99. package/lib/typescript/web/NodeManager.d.ts +2 -2
  100. package/package.json +1 -1
  101. package/src/RNGestureHandlerModule.macos.ts +62 -0
  102. package/src/components/DrawerLayout.tsx +34 -10
  103. package/src/components/GestureButtons.tsx +7 -0
  104. package/src/components/touchables/GenericTouchable.tsx +1 -0
  105. package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +1 -0
  106. package/src/handlers/ForceTouchGestureHandler.ts +3 -2
  107. package/src/handlers/PanGestureHandler.ts +2 -0
  108. package/src/handlers/PressabilityDebugView.tsx +2 -0
  109. package/src/handlers/PressabilityDebugView.web.tsx +4 -0
  110. package/src/handlers/{createHandler.ts → createHandler.tsx} +32 -17
  111. package/src/handlers/gestureHandlerCommon.ts +2 -0
  112. package/src/handlers/gestures/GestureDetector.tsx +107 -81
  113. package/src/handlers/gestures/gesture.ts +16 -0
  114. package/src/handlers/gestures/gestureStateManager.ts +13 -8
  115. package/src/handlers/gestures/panGesture.ts +5 -0
  116. package/src/mocks.ts +2 -0
  117. package/src/utils.ts +3 -1
  118. package/src/web/utils.ts +1 -1
  119. package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcuserdata/jakubpiasecki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  120. package/ios/RNGestureHandler.xcodeproj/xcuserdata/jakubpiasecki.xcuserdatad/xcschemes/xcschememanagement.plist +0 -19
@@ -9,6 +9,8 @@ import android.graphics.drawable.Drawable
9
9
  import android.graphics.drawable.LayerDrawable
10
10
  import android.graphics.drawable.PaintDrawable
11
11
  import android.graphics.drawable.RippleDrawable
12
+ import android.graphics.drawable.ShapeDrawable
13
+ import android.graphics.drawable.shapes.RectShape
12
14
  import android.os.Build
13
15
  import android.util.TypedValue
14
16
  import android.view.MotionEvent
@@ -16,7 +18,6 @@ import android.view.View
16
18
  import android.view.View.OnClickListener
17
19
  import android.view.ViewGroup
18
20
  import androidx.core.view.children
19
- import com.facebook.react.bridge.SoftAssertions
20
21
  import com.facebook.react.module.annotations.ReactModule
21
22
  import com.facebook.react.uimanager.PixelUtil
22
23
  import com.facebook.react.uimanager.ThemedReactContext
@@ -77,6 +78,11 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
77
78
  view.exclusive = exclusive
78
79
  }
79
80
 
81
+ @ReactProp(name = "touchSoundDisabled")
82
+ override fun setTouchSoundDisabled(view: ButtonViewGroup, touchSoundDisabled: Boolean) {
83
+ view.isSoundEffectsEnabled = !touchSoundDisabled
84
+ }
85
+
80
86
  override fun onAfterUpdateTransaction(view: ButtonViewGroup) {
81
87
  view.updateBackground()
82
88
  }
@@ -86,7 +92,7 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
86
92
  }
87
93
 
88
94
  class ButtonViewGroup(context: Context?) : ViewGroup(context),
89
- NativeViewGestureHandler.StateChangeHook {
95
+ NativeViewGestureHandler.NativeViewGestureHandlerHook {
90
96
  // Using object because of handling null representing no value set.
91
97
  var rippleColor: Int? = null
92
98
  set(color) = withBackgroundUpdate {
@@ -132,30 +138,6 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
132
138
  _backgroundColor = color
133
139
  }
134
140
 
135
- private fun applyRippleEffectWhenNeeded(selectable: Drawable): Drawable {
136
- val rippleColor = rippleColor
137
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && selectable is RippleDrawable) {
138
- val states = arrayOf(intArrayOf(android.R.attr.state_enabled))
139
- val colorStateList = if (rippleColor != null) {
140
- val colors = intArrayOf(rippleColor)
141
- ColorStateList(states, colors)
142
- } else {
143
- // if rippleColor is null, reapply the default color
144
- context.theme.resolveAttribute(android.R.attr.colorControlHighlight, resolveOutValue, true)
145
- val colors = intArrayOf(resolveOutValue.data)
146
- ColorStateList(states, colors)
147
- }
148
-
149
- selectable.setColor(colorStateList)
150
- }
151
-
152
- val rippleRadius = rippleRadius
153
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && rippleRadius != null && selectable is RippleDrawable) {
154
- selectable.radius = PixelUtil.toPixelFromDIP(rippleRadius.toFloat()).toInt()
155
- }
156
- return selectable
157
- }
158
-
159
141
  override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
160
142
  if (super.onInterceptTouchEvent(ev)) {
161
143
  return true
@@ -210,49 +192,74 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
210
192
  // reset foreground
211
193
  foreground = null
212
194
  }
195
+
196
+ val selectable = createSelectableDrawable()
197
+
198
+ if (borderRadius != 0f) {
199
+ // Radius-connected lines below ought to be considered
200
+ // as a temporary solution. It do not allow to set
201
+ // different radius on each corner. However, I suppose it's fairly
202
+ // fine for button-related use cases.
203
+ // Therefore it might be used as long as:
204
+ // 1. ReactViewManager is not a generic class with a possibility to handle another ViewGroup
205
+ // 2. There's no way to force native behavior of ReactViewGroup's superclass's onTouchEvent
206
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && selectable is RippleDrawable) {
207
+ val mask = PaintDrawable(Color.WHITE)
208
+ mask.setCornerRadius(borderRadius)
209
+ selectable.setDrawableByLayerId(android.R.id.mask, mask)
210
+ }
211
+ }
212
+
213
213
  if (useDrawableOnForeground && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
214
- foreground = applyRippleEffectWhenNeeded(createSelectableDrawable())
214
+ foreground = selectable
215
215
  if (_backgroundColor != Color.TRANSPARENT) {
216
216
  setBackgroundColor(_backgroundColor)
217
217
  }
218
218
  } else if (_backgroundColor == Color.TRANSPARENT && rippleColor == null) {
219
- background = createSelectableDrawable()
219
+ background = selectable
220
220
  } else {
221
221
  val colorDrawable = PaintDrawable(_backgroundColor)
222
- val selectable = createSelectableDrawable()
222
+
223
223
  if (borderRadius != 0f) {
224
- // Radius-connected lines below ought to be considered
225
- // as a temporary solution. It do not allow to set
226
- // different radius on each corner. However, I suppose it's fairly
227
- // fine for button-related use cases.
228
- // Therefore it might be used as long as:
229
- // 1. ReactViewManager is not a generic class with a possibility to handle another ViewGroup
230
- // 2. There's no way to force native behavior of ReactViewGroup's superclass's onTouchEvent
231
224
  colorDrawable.setCornerRadius(borderRadius)
232
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
233
- && selectable is RippleDrawable) {
234
- val mask = PaintDrawable(Color.WHITE)
235
- mask.setCornerRadius(borderRadius)
236
- selectable.setDrawableByLayerId(android.R.id.mask, mask)
237
- }
238
225
  }
239
- applyRippleEffectWhenNeeded(selectable)
226
+
240
227
  val layerDrawable = LayerDrawable(arrayOf(colorDrawable, selectable))
241
228
  background = layerDrawable
242
229
  }
243
230
  }
244
231
 
245
232
  private fun createSelectableDrawable(): Drawable {
246
- val version = Build.VERSION.SDK_INT
247
- val identifier = if (useBorderlessDrawable && version >= 21) SELECTABLE_ITEM_BACKGROUND_BORDERLESS else SELECTABLE_ITEM_BACKGROUND
248
- val attrID = getAttrId(context, identifier)
249
- context.theme.resolveAttribute(attrID, resolveOutValue, true)
250
- return if (version >= 21) {
251
- resources.getDrawable(resolveOutValue.resourceId, context.theme)
252
- } else {
233
+ // TODO: remove once support for RN 0.63 is dropped, since 0.64 minSdkVersion is 21
234
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
235
+ context.theme.resolveAttribute(android.R.attr.selectableItemBackground, resolveOutValue, true)
253
236
  @Suppress("Deprecation")
254
- resources.getDrawable(resolveOutValue.resourceId)
237
+ return resources.getDrawable(resolveOutValue.resourceId)
238
+ }
239
+
240
+ val states = arrayOf(intArrayOf(android.R.attr.state_enabled))
241
+ val rippleRadius = rippleRadius
242
+ val colorStateList = if (rippleColor != null) {
243
+ val colors = intArrayOf(rippleColor!!)
244
+ ColorStateList(states, colors)
245
+ } else {
246
+ // if rippleColor is null, reapply the default color
247
+ context.theme.resolveAttribute(android.R.attr.colorControlHighlight, resolveOutValue, true)
248
+ val colors = intArrayOf(resolveOutValue.data)
249
+ ColorStateList(states, colors)
250
+ }
251
+
252
+ val drawable = RippleDrawable(
253
+ colorStateList,
254
+ null,
255
+ if (useBorderlessDrawable) null else ShapeDrawable(RectShape())
256
+ )
257
+
258
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && rippleRadius != null) {
259
+ drawable.radius = PixelUtil.toPixelFromDIP(rippleRadius.toFloat()).toInt()
255
260
  }
261
+
262
+ return drawable
256
263
  }
257
264
 
258
265
  override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
@@ -265,7 +272,7 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
265
272
  }
266
273
  }
267
274
 
268
- override fun canStart(): Boolean {
275
+ override fun canBegin(): Boolean {
269
276
  val isResponder = tryGrabbingResponder()
270
277
  if (isResponder) {
271
278
  isTouched = true
@@ -273,11 +280,6 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
273
280
  return isResponder
274
281
  }
275
282
 
276
- override fun afterGestureEnd() {
277
- tryFreeingResponder()
278
- isTouched = false
279
- }
280
-
281
283
  private fun tryGrabbingResponder(): Boolean {
282
284
  if (isChildTouched()) {
283
285
  return false
@@ -294,24 +296,30 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
294
296
  }
295
297
  }
296
298
 
297
- private fun tryFreeingResponder() {
298
- if (responder === this) {
299
- responder = null
300
- }
301
- }
302
-
303
299
  private fun isChildTouched(children: Sequence<View> = this.children): Boolean {
304
300
  for (child in children) {
305
301
  if (child is ButtonViewGroup && (child.isTouched || child.isPressed)) {
306
302
  return true
307
303
  } else if (child is ViewGroup) {
308
- return isChildTouched(child.children)
304
+ if (isChildTouched(child.children)) {
305
+ return true
306
+ }
309
307
  }
310
308
  }
311
309
 
312
310
  return false
313
311
  }
314
312
 
313
+ override fun performClick(): Boolean {
314
+ // don't preform click when a child button is pressed (mainly to prevent sound effect of
315
+ // a parent button from playing)
316
+ return if (!isChildTouched()) {
317
+ super.performClick()
318
+ } else {
319
+ false
320
+ }
321
+ }
322
+
315
323
  override fun setPressed(pressed: Boolean) {
316
324
  // there is a possibility of this method being called before NativeViewGestureHandler has
317
325
  // opportunity to call canStart, in that case we need to grab responder in case the gesture
@@ -329,12 +337,13 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
329
337
  if (!pressed || responder === this || canBePressedAlongsideOther) {
330
338
  // we set pressed state only for current responder or any non-exclusive button when responder
331
339
  // is null or non-exclusive, assuming it doesn't have pressed children
332
- super.setPressed(pressed)
333
340
  isTouched = pressed
341
+ super.setPressed(pressed)
334
342
  }
335
343
  if (!pressed && responder === this) {
336
344
  // if the responder is no longer pressed we release button responder
337
345
  responder = null
346
+ isTouched = false
338
347
  }
339
348
  }
340
349
 
@@ -344,28 +353,9 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
344
353
  }
345
354
 
346
355
  companion object {
347
- const val SELECTABLE_ITEM_BACKGROUND = "selectableItemBackground"
348
- const val SELECTABLE_ITEM_BACKGROUND_BORDERLESS = "selectableItemBackgroundBorderless"
349
-
350
356
  var resolveOutValue = TypedValue()
351
357
  var responder: ButtonViewGroup? = null
352
358
  var dummyClickListener = OnClickListener { }
353
-
354
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
355
- private fun getAttrId(context: Context, attr: String): Int {
356
- SoftAssertions.assertNotNull(attr)
357
- return when (attr) {
358
- SELECTABLE_ITEM_BACKGROUND -> {
359
- android.R.attr.selectableItemBackground
360
- }
361
- SELECTABLE_ITEM_BACKGROUND_BORDERLESS -> {
362
- android.R.attr.selectableItemBackgroundBorderless
363
- }
364
- else -> {
365
- context.resources.getIdentifier(attr, "attr", "android")
366
- }
367
- }
368
- }
369
359
  }
370
360
  }
371
361
 
@@ -224,6 +224,9 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?)
224
224
  if (config.hasKey(KEY_PAN_AVG_TOUCHES)) {
225
225
  handler.setAverageTouches(config.getBoolean(KEY_PAN_AVG_TOUCHES))
226
226
  }
227
+ if (config.hasKey(KEY_PAN_ACTIVATE_AFTER_LONG_PRESS)) {
228
+ handler.setActivateAfterLongPress(config.getInt(KEY_PAN_ACTIVATE_AFTER_LONG_PRESS).toLong())
229
+ }
227
230
  }
228
231
 
229
232
  override fun extractEventData(handler: PanGestureHandler, eventData: WritableMap) {
@@ -656,6 +659,7 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?)
656
659
  private const val KEY_PAN_MIN_POINTERS = "minPointers"
657
660
  private const val KEY_PAN_MAX_POINTERS = "maxPointers"
658
661
  private const val KEY_PAN_AVG_TOUCHES = "avgTouches"
662
+ private const val KEY_PAN_ACTIVATE_AFTER_LONG_PRESS = "activateAfterLongPress"
659
663
  private const val KEY_NUMBER_OF_POINTERS = "numberOfPointers"
660
664
  private const val KEY_DIRECTION = "direction"
661
665
 
@@ -28,7 +28,7 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni
28
28
  LOCAL_SHARED_LIBRARIES := libjsi \
29
29
  libfbjni \
30
30
  libglog \
31
- libfolly_json \
31
+ libfolly_runtime \
32
32
  libyoga \
33
33
  libreact_nativemodule_core \
34
34
  libturbomodulejsijni \
@@ -36,7 +36,6 @@ LOCAL_SHARED_LIBRARIES := libjsi \
36
36
  libreact_render_core \
37
37
  libreact_render_graphics \
38
38
  libfabricjni \
39
- libfolly_futures \
40
39
  libreact_debug \
41
40
  libreact_render_componentregistry \
42
41
  libreact_render_debug \
@@ -1,11 +1,11 @@
1
1
  /**
2
- * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
- *
4
- * Do not edit this file as changes may cause incorrect behavior and will be lost
5
- * once the code is regenerated.
6
- *
7
- * @generated by codegen project: GeneratePropsJavaDelegate.js
8
- */
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaDelegate.js
8
+ */
9
9
 
10
10
  package com.facebook.react.viewmanagers;
11
11
 
@@ -23,7 +23,7 @@ public class RNGestureHandlerButtonManagerDelegate<T extends View, U extends Bas
23
23
  public void setProperty(T view, String propName, @Nullable Object value) {
24
24
  switch (propName) {
25
25
  case "exclusive":
26
- mViewManager.setExclusive(view, value == null ? false : (boolean) value);
26
+ mViewManager.setExclusive(view, value == null ? true : (boolean) value);
27
27
  break;
28
28
  case "foreground":
29
29
  mViewManager.setForeground(view, value == null ? false : (boolean) value);
@@ -32,7 +32,7 @@ public class RNGestureHandlerButtonManagerDelegate<T extends View, U extends Bas
32
32
  mViewManager.setBorderless(view, value == null ? false : (boolean) value);
33
33
  break;
34
34
  case "enabled":
35
- mViewManager.setEnabled(view, value == null ? false : (boolean) value);
35
+ mViewManager.setEnabled(view, value == null ? true : (boolean) value);
36
36
  break;
37
37
  case "rippleColor":
38
38
  mViewManager.setRippleColor(view, ColorPropConverter.getColor(value, view.getContext()));
@@ -40,6 +40,9 @@ public class RNGestureHandlerButtonManagerDelegate<T extends View, U extends Bas
40
40
  case "rippleRadius":
41
41
  mViewManager.setRippleRadius(view, value == null ? 0 : ((Double) value).intValue());
42
42
  break;
43
+ case "touchSoundDisabled":
44
+ mViewManager.setTouchSoundDisabled(view, value == null ? false : (boolean) value);
45
+ break;
43
46
  default:
44
47
  super.setProperty(view, propName, value);
45
48
  }
@@ -19,4 +19,5 @@ public interface RNGestureHandlerButtonManagerInterface<T extends View> {
19
19
  void setEnabled(T view, boolean value);
20
20
  void setRippleColor(T view, @Nullable Integer value);
21
21
  void setRippleRadius(T view, int value);
22
+ void setTouchSoundDisabled(T view, boolean value);
22
23
  }
@@ -8,38 +8,54 @@
8
8
 
9
9
  @implementation RNBetterSwipeGestureRecognizer {
10
10
  __weak RNGestureHandler* _gestureHandler;
11
+ CGPoint _lastPoint; // location of the most recently updated touch, relative to the view
12
+ bool _hasBegan; // whether the `BEGAN` event has been sent
11
13
  }
12
14
 
13
15
  - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
14
16
  {
15
17
  if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
16
18
  _gestureHandler = gestureHandler;
19
+ _lastPoint = CGPointZero;
20
+ _hasBegan = NO;
17
21
  }
18
22
  return self;
19
23
  }
20
24
 
21
25
  - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
22
26
  {
27
+ _lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
23
28
  [_gestureHandler reset];
24
- [self triggerAction];
25
29
  [super touchesBegan:touches withEvent:event];
30
+
31
+ // self.numberOfTouches doesn't work for this because in case than one finger is required,
32
+ // when holding one finger on the screen and tapping with the second one, numberOfTouches is equal
33
+ // to 2 only for the first tap but 1 for all the following ones
34
+ if (!_hasBegan) {
35
+ [self triggerAction];
36
+ _hasBegan = YES;
37
+ }
38
+
26
39
  [_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
27
40
  }
28
41
 
29
42
  - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
30
43
  {
44
+ _lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
31
45
  [super touchesMoved:touches withEvent:event];
32
46
  [_gestureHandler.pointerTracker touchesMoved:touches withEvent:event];
33
47
  }
34
48
 
35
49
  - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
36
50
  {
51
+ _lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
37
52
  [super touchesEnded:touches withEvent:event];
38
53
  [_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
39
54
  }
40
55
 
41
56
  - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
42
57
  {
58
+ _lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
43
59
  [super touchesCancelled:touches withEvent:event];
44
60
  [_gestureHandler.pointerTracker touchesCancelled:touches withEvent:event];
45
61
  }
@@ -53,9 +69,17 @@
53
69
  {
54
70
  [self triggerAction];
55
71
  [_gestureHandler.pointerTracker reset];
72
+ _hasBegan = NO;
56
73
  [super reset];
57
74
  }
58
75
 
76
+ - (CGPoint)getLastLocation {
77
+ // I think keeping the location of only one touch is enough since it would be used to determine the direction
78
+ // of the movement, and if it's wrong the recognizer fails anyway.
79
+ // In case the location of all touches is required, touch events are the way to go
80
+ return _lastPoint;
81
+ }
82
+
59
83
  @end
60
84
 
61
85
  @implementation RNFlingGestureHandler
@@ -104,5 +128,23 @@
104
128
  return shouldBegin;
105
129
  }
106
130
 
131
+ - (RNGestureHandlerEventExtraData *)eventExtraData:(id)_recognizer
132
+ {
133
+ // For some weird reason [recognizer locationInView:recognizer.view.window] returns (0, 0).
134
+ // To calculate the correct absolute position, first calculate the absolute position of the
135
+ // view inside the root view controller (https://stackoverflow.com/a/7448573) and then
136
+ // add the relative touch position to it.
137
+
138
+ RNBetterSwipeGestureRecognizer *recognizer = (RNBetterSwipeGestureRecognizer *)_recognizer;
139
+
140
+ CGPoint viewAbsolutePosition = [recognizer.view convertPoint:recognizer.view.bounds.origin toView:[UIApplication sharedApplication].keyWindow.rootViewController.view];
141
+ CGPoint locationInView = [recognizer getLastLocation];
142
+
143
+ return [RNGestureHandlerEventExtraData
144
+ forPosition:locationInView
145
+ withAbsolutePosition:CGPointMake(viewAbsolutePosition.x + locationInView.x, viewAbsolutePosition.y + locationInView.y)
146
+ withNumberOfTouches:recognizer.numberOfTouches];
147
+ }
148
+
107
149
  @end
108
150
 
@@ -11,9 +11,14 @@
11
11
  #import <UIKit/UIGestureRecognizerSubclass.h>
12
12
 
13
13
  #import <React/RCTConvert.h>
14
- #import <React/RCTScrollView.h>
15
14
  #import <React/UIView+React.h>
16
15
 
16
+ #ifdef RN_FABRIC_ENABLED
17
+ #import <React/RCTScrollViewComponentView.h>
18
+ #else
19
+ #import <React/RCTScrollView.h>
20
+ #endif // RN_FABRIC_ENABLED
21
+
17
22
  #pragma mark RNDummyGestureRecognizer
18
23
 
19
24
  @implementation RNDummyGestureRecognizer {
@@ -101,6 +106,12 @@
101
106
  // We can restore default scrollview behaviour to delay touches to scrollview's children
102
107
  // because gesture handler system can handle cancellation of scroll recognizer when JS responder
103
108
  // is set
109
+ #ifdef RN_FABRIC_ENABLED
110
+ if ([view isKindOfClass:[RCTScrollViewComponentView class]]) {
111
+ UIScrollView *scrollView = ((RCTScrollViewComponentView *)view).scrollView;
112
+ scrollView.delaysContentTouches = YES;
113
+ }
114
+ #else
104
115
  if ([view isKindOfClass:[RCTScrollView class]]) {
105
116
  // This part of the code is coupled with RN implementation of ScrollView native wrapper and
106
117
  // we expect for RCTScrollView component to contain a subclass of UIScrollview as the only
@@ -108,6 +119,7 @@
108
119
  UIScrollView *scrollView = [view.subviews objectAtIndex:0];
109
120
  scrollView.delaysContentTouches = YES;
110
121
  }
122
+ #endif // RN_FABRIC_ENABLED
111
123
  }
112
124
 
113
125
  - (void)handleTouchDown:(UIView *)sender forEvent:(UIEvent *)event
@@ -24,6 +24,7 @@
24
24
  @property (nonatomic) CGFloat activeOffsetYEnd;
25
25
  @property (nonatomic) CGFloat failOffsetYStart;
26
26
  @property (nonatomic) CGFloat failOffsetYEnd;
27
+ @property (nonatomic) CGFloat activateAfterLongPress;
27
28
 
28
29
 
29
30
  - (id)initWithGestureHandler:(RNGestureHandler*)gestureHandler;
@@ -53,6 +54,7 @@
53
54
  _activeOffsetYEnd = NAN;
54
55
  _failOffsetYStart = NAN;
55
56
  _failOffsetYEnd = NAN;
57
+ _activateAfterLongPress = NAN;
56
58
  _hasCustomActivationCriteria = NO;
57
59
  #if !TARGET_OS_TV
58
60
  _realMinimumNumberOfTouches = self.minimumNumberOfTouches;
@@ -71,6 +73,13 @@
71
73
  _realMinimumNumberOfTouches = minimumNumberOfTouches;
72
74
  }
73
75
 
76
+ - (void)activateAfterLongPress
77
+ {
78
+ self.state = UIGestureRecognizerStateBegan;
79
+ // Send event in ACTIVE state because UIGestureRecognizerStateBegan is mapped to RNGestureHandlerStateBegan
80
+ [_gestureHandler handleGesture:self inState:RNGestureHandlerStateActive];
81
+ }
82
+
74
83
  - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
75
84
  {
76
85
  if ([self numberOfTouches] == 0) {
@@ -89,6 +98,10 @@
89
98
  [super touchesBegan:touches withEvent:event];
90
99
  [self triggerAction];
91
100
  [_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
101
+
102
+ if (!isnan(_activateAfterLongPress)) {
103
+ [self performSelector:@selector(activateAfterLongPress) withObject:nil afterDelay:_activateAfterLongPress];
104
+ }
92
105
  }
93
106
 
94
107
  - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
@@ -140,6 +153,7 @@
140
153
  {
141
154
  [self triggerAction];
142
155
  [_gestureHandler.pointerTracker reset];
156
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(activateAfterLongPress) object:nil];
143
157
  self.enabled = YES;
144
158
  [super reset];
145
159
  }
@@ -155,6 +169,12 @@
155
169
  - (BOOL)shouldFailUnderCustomCriteria
156
170
  {
157
171
  CGPoint trans = [self translationInView:self.view.window];
172
+ // Apple docs say that 10 units is the default allowable movement for UILongPressGestureRecognizer
173
+ if (!isnan(_activateAfterLongPress) && trans.x * trans.x + trans.y * trans.y > 100) {
174
+ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(activateAfterLongPress) object:nil];
175
+ return YES;
176
+ }
177
+
158
178
  if (!isnan(_failOffsetXStart) && trans.x < _failOffsetXStart) {
159
179
  return YES;
160
180
  }
@@ -242,6 +262,7 @@
242
262
  #endif
243
263
  recognizer.minDistSq = NAN;
244
264
  recognizer.minVelocitySq = NAN;
265
+ recognizer.activateAfterLongPress = NAN;
245
266
  }
246
267
 
247
268
  - (void)configure:(NSDictionary *)config
@@ -283,6 +304,12 @@
283
304
  CGFloat velocity = [RCTConvert CGFloat:prop];
284
305
  recognizer.minVelocitySq = velocity * velocity;
285
306
  }
307
+
308
+ prop = config[@"activateAfterLongPress"];
309
+ if (prop != nil) {
310
+ recognizer.activateAfterLongPress = [RCTConvert CGFloat:prop] / 1000.0;
311
+ recognizer.minDistSq = MAX(100, recognizer.minDistSq);
312
+ }
286
313
  [recognizer updateHasCustomActivationCriteria];
287
314
  }
288
315
 
@@ -65,6 +65,7 @@ if (value != nil) { recognizer.prop = [RCTConvert type:value]; }\
65
65
  - (void)resetConfig NS_REQUIRES_SUPER;
66
66
  - (void)configure:(nullable NSDictionary *)config NS_REQUIRES_SUPER;
67
67
  - (void)handleGesture:(nonnull id)recognizer;
68
+ - (void)handleGesture:(nonnull id)recognizer inState:(RNGestureHandlerState)state;
68
69
  - (BOOL)containsPointInView;
69
70
  - (RNGestureHandlerState)state;
70
71
  - (nullable RNGestureHandlerEventExtraData *)eventExtraData:(nonnull id)recognizer;
@@ -203,6 +203,12 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
203
203
  }
204
204
 
205
205
  _state = [self recognizerState];
206
+ [self handleGesture:recognizer inState:_state];
207
+ }
208
+
209
+ - (void)handleGesture:(UIGestureRecognizer *)recognizer inState:(RNGestureHandlerState)state
210
+ {
211
+ _state = state;
206
212
  RNGestureHandlerEventExtraData *eventData = [self eventExtraData:recognizer];
207
213
  [self sendEventsInState:self.state forViewWithTag:recognizer.view.reactTag withExtraData:eventData];
208
214
  }
@@ -212,6 +218,11 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
212
218
  withExtraData:(RNGestureHandlerEventExtraData *)extraData
213
219
  {
214
220
  if (state != _lastState) {
221
+ // don't send change events from END to FAILED or CANCELLED, this may happen when gesture is ended in `onTouchesUp` callback
222
+ if (_lastState == RNGestureHandlerStateEnd && (state == RNGestureHandlerStateFailed || state == RNGestureHandlerStateCancelled)) {
223
+ return;
224
+ }
225
+
215
226
  if (state == RNGestureHandlerStateActive) {
216
227
  // Generate a unique coalescing-key each time the gesture-handler becomes active. All events will have
217
228
  // the same coalescing-key allowing RCTEventDispatcher to coalesce RNGestureHandlerEvents when events are
@@ -219,7 +230,7 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
219
230
  static uint16_t nextEventCoalescingKey = 0;
220
231
  self->_eventCoalescingKey = nextEventCoalescingKey++;
221
232
 
222
- } else if (state == RNGestureHandlerStateEnd && _lastState != RNGestureHandlerStateActive) {
233
+ } else if (state == RNGestureHandlerStateEnd && _lastState != RNGestureHandlerStateActive && !_manualActivation) {
223
234
  id event = [[RNGestureHandlerStateChange alloc] initWithReactTag:reactTag
224
235
  handlerTag:_tag
225
236
  state:RNGestureHandlerStateActive
@@ -390,14 +401,21 @@ shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherG
390
401
  if (_recognizer.state == UIGestureRecognizerStateBegan && _recognizer.state == UIGestureRecognizerStatePossible) {
391
402
  return YES;
392
403
  }
393
- if ([_simultaneousHandlers count]) {
394
- RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
395
- if (handler != nil) {
404
+
405
+ RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
406
+ if (handler != nil) {
407
+ if ([_simultaneousHandlers count]) {
396
408
  for (NSNumber *handlerTag in _simultaneousHandlers) {
397
409
  if ([handler.tag isEqual:handlerTag]) {
398
410
  return YES;
399
411
  }
400
412
  }
413
+ } else if (handler->_simultaneousHandlers) {
414
+ for (NSNumber *handlerTag in handler->_simultaneousHandlers) {
415
+ if ([self.tag isEqual:handlerTag]) {
416
+ return YES;
417
+ }
418
+ }
401
419
  }
402
420
  }
403
421
  return NO;
@@ -4,7 +4,6 @@
4
4
  #import <React/RCTViewManager.h>
5
5
  #import <React/RCTComponent.h>
6
6
  #import <React/RCTRootView.h>
7
- #import <React/RCTTouchHandler.h>
8
7
  #import <React/RCTUIManager.h>
9
8
  #import <React/RCTEventDispatcher.h>
10
9
 
@@ -22,6 +21,9 @@
22
21
 
23
22
  #ifdef RN_FABRIC_ENABLED
24
23
  #import <React/RCTViewComponentView.h>
24
+ #import <React/RCTSurfaceTouchHandler.h>
25
+ #else
26
+ #import <React/RCTTouchHandler.h>
25
27
  #endif // RN_FABRIC_ENABLED
26
28
 
27
29
  #import "Handlers/RNPanHandler.h"
@@ -211,8 +213,14 @@
211
213
  // Once the upstream fix lands the line below along with this comment can be removed
212
214
  if ([gestureRecognizer.view isKindOfClass:[UIScrollView class]]) return;
213
215
 
216
+ #ifdef RN_FABRIC_ENABLED
217
+ RCTSurfaceTouchHandler *touchHandler = [viewWithTouchHandler performSelector:@selector(touchHandler)];
218
+ #else
214
219
  RCTTouchHandler *touchHandler = [viewWithTouchHandler performSelector:@selector(touchHandler)];
215
- [touchHandler cancel];
220
+ #endif
221
+ [touchHandler setEnabled:NO];
222
+ [touchHandler setEnabled:YES];
223
+
216
224
  }
217
225
 
218
226
  #pragma mark Events