react-native-gesture-handler 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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