react-native-gesture-handler 2.15.0 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (254) hide show
  1. package/RNGestureHandler.podspec +2 -23
  2. package/android/build.gradle +1 -1
  3. package/android/noreanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +2 -0
  4. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +9 -0
  5. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerInterface.java +3 -0
  6. package/android/src/main/java/com/swmansion/gesturehandler/RNGestureHandlerPackage.kt +11 -6
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/DiagonalDirections.kt +8 -0
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt +65 -24
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +86 -22
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +54 -29
  11. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureUtils.kt +3 -0
  12. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +5 -1
  13. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +5 -1
  14. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +7 -3
  15. package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +66 -0
  16. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +119 -19
  17. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEnabledRootView.kt +2 -2
  18. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEvent.kt +1 -4
  19. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +8 -5
  20. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +7 -4
  21. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +1 -1
  22. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerStateChangeEvent.kt +1 -4
  23. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerTouchEvent.kt +4 -7
  24. package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/GestureHandlerEventDataBuilder.kt +3 -0
  25. package/android/src/main/jni/cpp-adapter.cpp +18 -22
  26. package/apple/Handlers/RNFlingHandler.m +5 -4
  27. package/apple/Handlers/RNForceTouchHandler.m +3 -1
  28. package/apple/Handlers/RNHoverHandler.m +2 -1
  29. package/apple/Handlers/RNLongPressHandler.m +8 -14
  30. package/apple/Handlers/RNManualHandler.m +1 -0
  31. package/apple/Handlers/RNNativeViewHandler.mm +9 -7
  32. package/apple/Handlers/RNPanHandler.m +7 -2
  33. package/apple/Handlers/RNPinchHandler.m +50 -26
  34. package/apple/Handlers/RNRotationHandler.m +43 -29
  35. package/apple/Handlers/RNTapHandler.m +6 -4
  36. package/apple/RNGestureHandler.h +9 -0
  37. package/apple/RNGestureHandler.m +41 -4
  38. package/apple/RNGestureHandlerEvents.h +18 -9
  39. package/apple/RNGestureHandlerEvents.m +29 -11
  40. package/apple/RNGestureHandlerManager.h +5 -0
  41. package/apple/RNGestureHandlerManager.mm +32 -6
  42. package/apple/RNGestureHandlerModule.h +5 -3
  43. package/apple/RNGestureHandlerModule.mm +33 -19
  44. package/apple/RNGestureHandlerPointerType.h +8 -0
  45. package/lib/commonjs/Directions.js +19 -6
  46. package/lib/commonjs/Directions.js.map +1 -1
  47. package/lib/commonjs/PointerType.js +16 -0
  48. package/lib/commonjs/PointerType.js.map +1 -0
  49. package/lib/commonjs/RNGestureHandlerModule.web.js +7 -61
  50. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  51. package/lib/commonjs/components/DrawerLayout.js.map +1 -1
  52. package/lib/commonjs/components/GestureHandlerRootView.android.js +17 -2
  53. package/lib/commonjs/components/GestureHandlerRootView.android.js.map +1 -1
  54. package/lib/commonjs/components/GestureHandlerRootView.js +15 -2
  55. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  56. package/lib/commonjs/components/GestureHandlerRootView.web.js +15 -2
  57. package/lib/commonjs/components/GestureHandlerRootView.web.js.map +1 -1
  58. package/lib/commonjs/components/Swipeable.js +3 -1
  59. package/lib/commonjs/components/Swipeable.js.map +1 -1
  60. package/lib/commonjs/components/touchables/GenericTouchable.js +1 -0
  61. package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
  62. package/lib/commonjs/getShadowNodeFromRef.js +19 -2
  63. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
  64. package/lib/commonjs/handlers/createHandler.js +5 -0
  65. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  66. package/lib/commonjs/handlers/customDirectEventTypes.js +14 -0
  67. package/lib/commonjs/handlers/customDirectEventTypes.js.map +1 -0
  68. package/lib/commonjs/handlers/customDirectEventTypes.web.js +11 -0
  69. package/lib/commonjs/handlers/customDirectEventTypes.web.js.map +1 -0
  70. package/lib/commonjs/handlers/gestureHandlerCommon.js +13 -2
  71. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  72. package/lib/commonjs/handlers/gestures/GestureDetector.js +10 -0
  73. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  74. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  75. package/lib/commonjs/index.js +11 -3
  76. package/lib/commonjs/index.js.map +1 -1
  77. package/lib/commonjs/mocks.js +2 -0
  78. package/lib/commonjs/mocks.js.map +1 -1
  79. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  80. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  81. package/lib/commonjs/web/Gestures.js +66 -0
  82. package/lib/commonjs/web/Gestures.js.map +1 -0
  83. package/lib/commonjs/web/constants.js +3 -8
  84. package/lib/commonjs/web/constants.js.map +1 -1
  85. package/lib/commonjs/web/handlers/FlingGestureHandler.js +36 -12
  86. package/lib/commonjs/web/handlers/FlingGestureHandler.js.map +1 -1
  87. package/lib/commonjs/web/handlers/GestureHandler.js +10 -5
  88. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  89. package/lib/commonjs/web/handlers/IGestureHandler.js +2 -0
  90. package/lib/commonjs/web/handlers/IGestureHandler.js.map +1 -0
  91. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +5 -6
  92. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  93. package/lib/commonjs/web/interfaces.js +1 -23
  94. package/lib/commonjs/web/interfaces.js.map +1 -1
  95. package/lib/commonjs/web/tools/EventManager.js.map +1 -1
  96. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +117 -118
  97. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  98. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +10 -5
  99. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  100. package/lib/commonjs/web/tools/InteractionManager.js +12 -3
  101. package/lib/commonjs/web/tools/InteractionManager.js.map +1 -1
  102. package/lib/commonjs/web/tools/NodeManager.js.map +1 -1
  103. package/lib/commonjs/web/tools/PointerEventManager.js +77 -27
  104. package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
  105. package/lib/commonjs/web/tools/TouchEventManager.js +29 -6
  106. package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -1
  107. package/lib/commonjs/web/tools/Vector.js +58 -0
  108. package/lib/commonjs/web/tools/Vector.js.map +1 -0
  109. package/lib/commonjs/web/utils.js +14 -0
  110. package/lib/commonjs/web/utils.js.map +1 -1
  111. package/lib/commonjs/web_hammer/NodeManager.js.map +1 -1
  112. package/lib/module/Directions.js +16 -4
  113. package/lib/module/Directions.js.map +1 -1
  114. package/lib/module/PointerType.js +9 -0
  115. package/lib/module/PointerType.js.map +1 -0
  116. package/lib/module/RNGestureHandlerModule.web.js +2 -39
  117. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  118. package/lib/module/components/DrawerLayout.js.map +1 -1
  119. package/lib/module/components/GestureHandlerRootView.android.js +15 -2
  120. package/lib/module/components/GestureHandlerRootView.android.js.map +1 -1
  121. package/lib/module/components/GestureHandlerRootView.js +15 -3
  122. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  123. package/lib/module/components/GestureHandlerRootView.web.js +15 -3
  124. package/lib/module/components/GestureHandlerRootView.web.js.map +1 -1
  125. package/lib/module/components/Swipeable.js +3 -1
  126. package/lib/module/components/Swipeable.js.map +1 -1
  127. package/lib/module/components/touchables/GenericTouchable.js +1 -0
  128. package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
  129. package/lib/module/getShadowNodeFromRef.js +19 -2
  130. package/lib/module/getShadowNodeFromRef.js.map +1 -1
  131. package/lib/module/handlers/createHandler.js +5 -1
  132. package/lib/module/handlers/createHandler.js.map +1 -1
  133. package/lib/module/handlers/customDirectEventTypes.js +3 -0
  134. package/lib/module/handlers/customDirectEventTypes.js.map +1 -0
  135. package/lib/module/handlers/customDirectEventTypes.web.js +5 -0
  136. package/lib/module/handlers/customDirectEventTypes.web.js.map +1 -0
  137. package/lib/module/handlers/gestureHandlerCommon.js +11 -1
  138. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  139. package/lib/module/handlers/gestures/GestureDetector.js +10 -0
  140. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  141. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  142. package/lib/module/index.js +2 -1
  143. package/lib/module/index.js.map +1 -1
  144. package/lib/module/mocks.js +2 -0
  145. package/lib/module/mocks.js.map +1 -1
  146. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  147. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  148. package/lib/module/web/Gestures.js +39 -0
  149. package/lib/module/web/Gestures.js.map +1 -0
  150. package/lib/module/web/constants.js +1 -6
  151. package/lib/module/web/constants.js.map +1 -1
  152. package/lib/module/web/handlers/FlingGestureHandler.js +34 -12
  153. package/lib/module/web/handlers/FlingGestureHandler.js.map +1 -1
  154. package/lib/module/web/handlers/GestureHandler.js +7 -4
  155. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  156. package/lib/module/web/handlers/IGestureHandler.js +2 -0
  157. package/lib/module/web/handlers/IGestureHandler.js.map +1 -0
  158. package/lib/module/web/handlers/NativeViewGestureHandler.js +5 -6
  159. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  160. package/lib/module/web/interfaces.js +0 -20
  161. package/lib/module/web/interfaces.js.map +1 -1
  162. package/lib/module/web/tools/EventManager.js.map +1 -1
  163. package/lib/module/web/tools/GestureHandlerOrchestrator.js +116 -117
  164. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  165. package/lib/module/web/tools/GestureHandlerWebDelegate.js +9 -4
  166. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  167. package/lib/module/web/tools/InteractionManager.js +9 -3
  168. package/lib/module/web/tools/InteractionManager.js.map +1 -1
  169. package/lib/module/web/tools/NodeManager.js.map +1 -1
  170. package/lib/module/web/tools/PointerEventManager.js +75 -27
  171. package/lib/module/web/tools/PointerEventManager.js.map +1 -1
  172. package/lib/module/web/tools/TouchEventManager.js +28 -6
  173. package/lib/module/web/tools/TouchEventManager.js.map +1 -1
  174. package/lib/module/web/tools/Vector.js +47 -0
  175. package/lib/module/web/tools/Vector.js.map +1 -0
  176. package/lib/module/web/utils.js +4 -0
  177. package/lib/module/web/utils.js.map +1 -1
  178. package/lib/module/web_hammer/NodeManager.js.map +1 -1
  179. package/lib/typescript/Directions.d.ts +7 -0
  180. package/lib/typescript/PointerType.d.ts +6 -0
  181. package/lib/typescript/RNGestureHandlerModule.web.d.ts +4 -39
  182. package/lib/typescript/components/DrawerLayout.d.ts +1 -2
  183. package/lib/typescript/components/GestureHandlerRootView.android.d.ts +1 -1
  184. package/lib/typescript/components/GestureHandlerRootView.d.ts +1 -1
  185. package/lib/typescript/components/GestureHandlerRootView.web.d.ts +1 -1
  186. package/lib/typescript/components/touchables/GenericTouchable.d.ts +2 -1
  187. package/lib/typescript/getShadowNodeFromRef.d.ts +1 -1
  188. package/lib/typescript/handlers/NativeViewGestureHandler.d.ts +1 -1
  189. package/lib/typescript/handlers/customDirectEventTypes.d.ts +1 -0
  190. package/lib/typescript/handlers/customDirectEventTypes.web.d.ts +2 -0
  191. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +13 -2
  192. package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -1
  193. package/lib/typescript/handlers/gestures/gesture.d.ts +1 -2
  194. package/lib/typescript/index.d.ts +2 -1
  195. package/lib/typescript/mocks.d.ts +1 -0
  196. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +6 -6
  197. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +4 -1
  198. package/lib/typescript/web/Gestures.d.ts +36 -0
  199. package/lib/typescript/web/constants.d.ts +1 -6
  200. package/lib/typescript/web/handlers/FlingGestureHandler.d.ts +3 -3
  201. package/lib/typescript/web/handlers/GestureHandler.d.ts +12 -9
  202. package/lib/typescript/web/handlers/IGestureHandler.d.ts +38 -0
  203. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  204. package/lib/typescript/web/interfaces.d.ts +9 -16
  205. package/lib/typescript/web/tools/EventManager.d.ts +15 -12
  206. package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +3 -4
  207. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +7 -5
  208. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +3 -3
  209. package/lib/typescript/web/tools/InteractionManager.d.ts +6 -6
  210. package/lib/typescript/web/tools/NodeManager.d.ts +4 -3
  211. package/lib/typescript/web/tools/PointerEventManager.d.ts +11 -2
  212. package/lib/typescript/web/tools/TouchEventManager.d.ts +6 -1
  213. package/lib/typescript/web/tools/Vector.d.ts +15 -0
  214. package/lib/typescript/web/utils.d.ts +6 -4
  215. package/lib/typescript/web_hammer/NodeManager.d.ts +1 -1
  216. package/package.json +2 -1
  217. package/src/Directions.ts +21 -4
  218. package/src/PointerType.ts +6 -0
  219. package/src/RNGestureHandlerModule.web.ts +3 -44
  220. package/src/components/DrawerLayout.tsx +1 -1
  221. package/src/components/GestureHandlerRootView.android.tsx +13 -5
  222. package/src/components/GestureHandlerRootView.tsx +10 -5
  223. package/src/components/GestureHandlerRootView.web.tsx +10 -5
  224. package/src/components/Swipeable.tsx +2 -0
  225. package/src/components/touchables/GenericTouchable.tsx +3 -0
  226. package/src/getShadowNodeFromRef.ts +28 -6
  227. package/src/handlers/createHandler.tsx +14 -2
  228. package/src/handlers/customDirectEventTypes.ts +2 -0
  229. package/src/handlers/customDirectEventTypes.web.ts +5 -0
  230. package/src/handlers/gestureHandlerCommon.ts +30 -1
  231. package/src/handlers/gestures/GestureDetector.tsx +15 -0
  232. package/src/handlers/gestures/gesture.ts +1 -1
  233. package/src/index.ts +2 -1
  234. package/src/mocks.ts +2 -0
  235. package/src/specs/NativeRNGestureHandlerModule.ts +8 -8
  236. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +4 -0
  237. package/src/web/Gestures.ts +41 -0
  238. package/src/web/constants.ts +1 -7
  239. package/src/web/handlers/FlingGestureHandler.ts +54 -24
  240. package/src/web/handlers/GestureHandler.ts +17 -12
  241. package/src/web/handlers/IGestureHandler.ts +50 -0
  242. package/src/web/handlers/NativeViewGestureHandler.ts +5 -6
  243. package/src/web/interfaces.ts +15 -17
  244. package/src/web/tools/EventManager.ts +16 -14
  245. package/src/web/tools/GestureHandlerDelegate.ts +3 -4
  246. package/src/web/tools/GestureHandlerOrchestrator.ts +162 -147
  247. package/src/web/tools/GestureHandlerWebDelegate.ts +14 -9
  248. package/src/web/tools/InteractionManager.ts +18 -12
  249. package/src/web/tools/NodeManager.ts +4 -3
  250. package/src/web/tools/PointerEventManager.ts +189 -154
  251. package/src/web/tools/TouchEventManager.ts +128 -120
  252. package/src/web/tools/Vector.ts +60 -0
  253. package/src/web/utils.ts +16 -4
  254. package/src/web_hammer/NodeManager.ts +1 -1
@@ -1,8 +1,5 @@
1
1
  require "json"
2
2
 
3
- new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
4
- apple_platform = new_arch_enabled ? '11.0' : '9.0'
5
-
6
3
  Pod::Spec.new do |s|
7
4
  # NPM package specification
8
5
  package = JSON.parse(File.read(File.join(File.dirname(__FILE__), "package.json")))
@@ -16,29 +13,11 @@ Pod::Spec.new do |s|
16
13
  s.source = { :git => "https://github.com/software-mansion/react-native-gesture-handler", :tag => "#{s.version}" }
17
14
  s.source_files = "apple/**/*.{h,m,mm}"
18
15
  s.requires_arc = true
19
- s.platforms = { ios: apple_platform, tvos: apple_platform, osx: '10.15', visionos: '1.0' }
16
+ s.platforms = { ios: '11.0', tvos: '11.0', osx: '10.15', visionos: '1.0' }
20
17
 
21
18
  if defined?(install_modules_dependencies()) != nil
22
19
  install_modules_dependencies(s);
23
20
  else
24
- if new_arch_enabled
25
- folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
26
-
27
- s.pod_target_xcconfig = {
28
- 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"',
29
- 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
30
- }
31
- s.compiler_flags = folly_compiler_flags + ' -DRCT_NEW_ARCH_ENABLED'
32
-
33
- s.dependency "React"
34
- s.dependency "React-RCTFabric" # This is for fabric component
35
- s.dependency "React-Codegen"
36
- s.dependency "RCT-Folly"
37
- s.dependency "RCTRequired"
38
- s.dependency "RCTTypeSafety"
39
- s.dependency "ReactCommon/turbomodule/core"
40
- else
41
- s.dependency "React-Core"
42
- end
21
+ s.dependency "React-Core"
43
22
  end
44
23
  end
@@ -136,7 +136,7 @@ android {
136
136
  var appProject = rootProject.allprojects.find {it.plugins.hasPlugin('com.android.application')}
137
137
  externalNativeBuild {
138
138
  cmake {
139
- cppFlags "-O2", "-frtti", "-fexceptions", "-Wall", "-Werror", "-std=c++17", "-DANDROID"
139
+ cppFlags "-O2", "-frtti", "-fexceptions", "-Wall", "-Werror", "-std=c++20", "-DANDROID"
140
140
  arguments "-DAPP_BUILD_DIR=${appProject.buildDir}",
141
141
  "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}",
142
142
  "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
@@ -4,6 +4,8 @@ import com.facebook.react.bridge.ReactContext
4
4
  import com.facebook.react.uimanager.events.Event
5
5
 
6
6
  class ReanimatedEventDispatcher {
7
+ @Suppress("UNUSED_PARAMETER", "COMMENT_IN_SUPPRESSION")
8
+ // This is necessary on new architecture
7
9
  fun <T : Event<T>>sendEvent(event: T, reactApplicationContext: ReactContext) {
8
10
  // no-op
9
11
  }
@@ -43,6 +43,15 @@ public class RNGestureHandlerButtonManagerDelegate<T extends View, U extends Bas
43
43
  case "touchSoundDisabled":
44
44
  mViewManager.setTouchSoundDisabled(view, value == null ? false : (boolean) value);
45
45
  break;
46
+ case "borderWidth":
47
+ mViewManager.setBorderWidth(view, value == null ? 0f : ((Double) value).floatValue());
48
+ break;
49
+ case "borderColor":
50
+ mViewManager.setBorderColor(view, ColorPropConverter.getColor(value, view.getContext()));
51
+ break;
52
+ case "borderStyle":
53
+ mViewManager.setBorderStyle(view, value == null ? "solid" : (String) value);
54
+ break;
46
55
  default:
47
56
  super.setProperty(view, propName, value);
48
57
  }
@@ -20,4 +20,7 @@ public interface RNGestureHandlerButtonManagerInterface<T extends View> {
20
20
  void setRippleColor(T view, @Nullable Integer value);
21
21
  void setRippleRadius(T view, int value);
22
22
  void setTouchSoundDisabled(T view, boolean value);
23
+ void setBorderWidth(T view, float value);
24
+ void setBorderColor(T view, @Nullable Integer value);
25
+ void setBorderStyle(T view, @Nullable String value);
23
26
  }
@@ -6,14 +6,19 @@ import com.facebook.react.bridge.ModuleSpec
6
6
  import com.facebook.react.bridge.NativeModule
7
7
  import com.facebook.react.bridge.ReactApplicationContext
8
8
  import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.module.annotations.ReactModuleList
9
10
  import com.facebook.react.module.model.ReactModuleInfo
10
11
  import com.facebook.react.module.model.ReactModuleInfoProvider
11
- import com.facebook.react.turbomodule.core.interfaces.TurboModule
12
12
  import com.facebook.react.uimanager.ViewManager
13
13
  import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
14
14
  import com.swmansion.gesturehandler.react.RNGestureHandlerModule
15
15
  import com.swmansion.gesturehandler.react.RNGestureHandlerRootViewManager
16
16
 
17
+ @ReactModuleList(
18
+ nativeModules = [
19
+ RNGestureHandlerModule::class
20
+ ]
21
+ )
17
22
  class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPackage {
18
23
  private val viewManagers: Map<String, ModuleSpec> by lazy {
19
24
  mapOf(
@@ -44,7 +49,7 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
44
49
  ) = viewManagers[viewManagerName]?.provider?.get() as? ViewManager<*, *>
45
50
 
46
51
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
47
- return if (name == RNGestureHandlerModule.MODULE_NAME) {
52
+ return if (name == RNGestureHandlerModule.NAME) {
48
53
  RNGestureHandlerModule(reactContext)
49
54
  } else {
50
55
  null
@@ -55,20 +60,20 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
55
60
  try {
56
61
  val reactModuleInfoProviderClass =
57
62
  Class.forName("com.swmansion.gesturehandler.RNGestureHandlerPackage$\$ReactModuleInfoProvider")
58
- return reactModuleInfoProviderClass.newInstance() as ReactModuleInfoProvider
63
+ return reactModuleInfoProviderClass.getDeclaredConstructor().newInstance() as ReactModuleInfoProvider
59
64
  } catch (e: ClassNotFoundException) {
60
65
  return ReactModuleInfoProvider {
61
66
  val reactModule: ReactModule = RNGestureHandlerModule::class.java.getAnnotation(ReactModule::class.java)!!
62
67
 
63
68
  mutableMapOf(
64
- RNGestureHandlerModule.MODULE_NAME to ReactModuleInfo(
69
+ RNGestureHandlerModule.NAME to ReactModuleInfo(
65
70
  reactModule.name,
66
71
  RNGestureHandlerModule::class.java.name,
67
72
  reactModule.canOverrideExistingModule,
68
73
  reactModule.needsEagerInit,
69
- reactModule.hasConstants,
74
+ true, // Has constants is hardcoded to return true, so replacing it with `true` changes nothing.
70
75
  reactModule.isCxxModule,
71
- TurboModule::class.java.isAssignableFrom(RNGestureHandlerModule::class.java)
76
+ true
72
77
  )
73
78
  )
74
79
  }
@@ -0,0 +1,8 @@
1
+ package com.swmansion.gesturehandler.core
2
+
3
+ object DiagonalDirections {
4
+ const val DIRECTION_RIGHT_UP = GestureHandler.DIRECTION_RIGHT or GestureHandler.DIRECTION_UP
5
+ const val DIRECTION_RIGHT_DOWN = GestureHandler.DIRECTION_RIGHT or GestureHandler.DIRECTION_DOWN
6
+ const val DIRECTION_LEFT_UP = GestureHandler.DIRECTION_LEFT or GestureHandler.DIRECTION_UP
7
+ const val DIRECTION_LEFT_DOWN = GestureHandler.DIRECTION_LEFT or GestureHandler.DIRECTION_DOWN
8
+ }
@@ -3,18 +3,18 @@ package com.swmansion.gesturehandler.core
3
3
  import android.os.Handler
4
4
  import android.os.Looper
5
5
  import android.view.MotionEvent
6
+ import android.view.VelocityTracker
6
7
 
7
8
  class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
8
9
  var numberOfPointersRequired = DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
9
10
  var direction = DEFAULT_DIRECTION
10
11
 
11
12
  private val maxDurationMs = DEFAULT_MAX_DURATION_MS
12
- private val minAcceptableDelta = DEFAULT_MIN_ACCEPTABLE_DELTA
13
- private var startX = 0f
14
- private var startY = 0f
13
+ private val minVelocity = DEFAULT_MIN_VELOCITY
15
14
  private var handler: Handler? = null
16
15
  private var maxNumberOfPointersSimultaneously = 0
17
16
  private val failDelayed = Runnable { fail() }
17
+ private var velocityTracker: VelocityTracker? = null
18
18
 
19
19
  override fun resetConfig() {
20
20
  super.resetConfig()
@@ -23,8 +23,7 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
23
23
  }
24
24
 
25
25
  private fun startFling(event: MotionEvent) {
26
- startX = event.rawX
27
- startY = event.rawY
26
+ velocityTracker = VelocityTracker.obtain()
28
27
  begin()
29
28
  maxNumberOfPointersSimultaneously = 1
30
29
  if (handler == null) {
@@ -35,26 +34,48 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
35
34
  handler!!.postDelayed(failDelayed, maxDurationMs)
36
35
  }
37
36
 
38
- private fun tryEndFling(event: MotionEvent) = if (
39
- maxNumberOfPointersSimultaneously == numberOfPointersRequired &&
40
- (
41
- direction and DIRECTION_RIGHT != 0 &&
42
- event.rawX - startX > minAcceptableDelta ||
43
- direction and DIRECTION_LEFT != 0 &&
44
- startX - event.rawX > minAcceptableDelta ||
45
- direction and DIRECTION_UP != 0 &&
46
- startY - event.rawY > minAcceptableDelta ||
47
- direction and DIRECTION_DOWN != 0 &&
48
- event.rawY - startY > minAcceptableDelta
37
+ private fun tryEndFling(event: MotionEvent): Boolean {
38
+ addVelocityMovement(velocityTracker, event)
39
+
40
+ val velocityVector = Vector.fromVelocity(velocityTracker!!)
41
+
42
+ fun getVelocityAlignment(
43
+ direction: Int,
44
+ maxDeviationCosine: Double,
45
+ ): Boolean = (
46
+ (this.direction and direction) == direction &&
47
+ velocityVector.isSimilar(Vector.fromDirection(direction), maxDeviationCosine)
49
48
  )
50
- ) {
51
- handler!!.removeCallbacksAndMessages(null)
52
- activate()
53
- true
54
- } else {
55
- false
56
- }
57
49
 
50
+ val axialAlignmentsList = arrayOf(
51
+ DIRECTION_LEFT,
52
+ DIRECTION_RIGHT,
53
+ DIRECTION_UP,
54
+ DIRECTION_DOWN,
55
+ ).map { direction -> getVelocityAlignment(direction, MAX_AXIAL_DEVIATION) }
56
+
57
+ val diagonalAlignmentsList = arrayOf(
58
+ DiagonalDirections.DIRECTION_RIGHT_UP,
59
+ DiagonalDirections.DIRECTION_RIGHT_DOWN,
60
+ DiagonalDirections.DIRECTION_LEFT_UP,
61
+ DiagonalDirections.DIRECTION_LEFT_DOWN,
62
+ ).map { direction -> getVelocityAlignment(direction, MAX_DIAGONAL_DEVIATION) }
63
+
64
+ val isAligned = axialAlignmentsList.any { it } or diagonalAlignmentsList.any { it }
65
+ val isFast = velocityVector.magnitude > this.minVelocity
66
+
67
+ return if (
68
+ maxNumberOfPointersSimultaneously == numberOfPointersRequired &&
69
+ isAligned &&
70
+ isFast
71
+ ) {
72
+ handler!!.removeCallbacksAndMessages(null)
73
+ activate()
74
+ true
75
+ } else {
76
+ false
77
+ }
78
+ }
58
79
  override fun activate(force: Boolean) {
59
80
  super.activate(force)
60
81
  end()
@@ -67,6 +88,10 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
67
88
  }
68
89
 
69
90
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
91
+ if (!shouldActivateWithMouse(sourceEvent)) {
92
+ return
93
+ }
94
+
70
95
  val state = state
71
96
  if (state == STATE_UNDETERMINED) {
72
97
  startFling(sourceEvent)
@@ -88,13 +113,29 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
88
113
  }
89
114
 
90
115
  override fun onReset() {
116
+ velocityTracker?.recycle()
117
+ velocityTracker = null
91
118
  handler?.removeCallbacksAndMessages(null)
92
119
  }
93
120
 
121
+ private fun addVelocityMovement(tracker: VelocityTracker?, event: MotionEvent) {
122
+ val offsetX = event.rawX - event.x
123
+ val offsetY = event.rawY - event.y
124
+ event.offsetLocation(offsetX, offsetY)
125
+ tracker!!.addMovement(event)
126
+ event.offsetLocation(-offsetX, -offsetY)
127
+ }
128
+
94
129
  companion object {
95
130
  private const val DEFAULT_MAX_DURATION_MS: Long = 800
96
- private const val DEFAULT_MIN_ACCEPTABLE_DELTA: Long = 160
131
+ private const val DEFAULT_MIN_VELOCITY: Long = 2000
132
+ private const val DEFAULT_ALIGNMENT_CONE: Double = 30.0
97
133
  private const val DEFAULT_DIRECTION = DIRECTION_RIGHT
98
134
  private const val DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1
135
+
136
+ private val MAX_AXIAL_DEVIATION: Double =
137
+ GestureUtils.coneToDeviation(DEFAULT_ALIGNMENT_CONE)
138
+ private val MAX_DIAGONAL_DEVIATION: Double =
139
+ GestureUtils.coneToDeviation(90 - DEFAULT_ALIGNMENT_CONE)
99
140
  }
100
141
  }
@@ -4,13 +4,13 @@ import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.content.ContextWrapper
6
6
  import android.graphics.PointF
7
- import android.graphics.Rect
7
+ import android.os.Build
8
8
  import android.view.MotionEvent
9
9
  import android.view.MotionEvent.PointerCoords
10
10
  import android.view.MotionEvent.PointerProperties
11
11
  import android.view.View
12
- import android.view.Window
13
12
  import com.facebook.react.bridge.Arguments
13
+ import com.facebook.react.bridge.ReactContext
14
14
  import com.facebook.react.bridge.UiThreadUtil
15
15
  import com.facebook.react.bridge.WritableArray
16
16
  import com.facebook.react.uimanager.PixelUtil
@@ -67,6 +67,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
67
67
  protected var orchestrator: GestureHandlerOrchestrator? = null
68
68
  private var onTouchEventListener: OnTouchEventListener? = null
69
69
  private var interactionController: GestureHandlerInteractionController? = null
70
+ var pointerType: Int = POINTER_TYPE_OTHER
71
+ private set
72
+
73
+ protected var mouseButton = 0
70
74
 
71
75
  @Suppress("UNCHECKED_CAST")
72
76
  protected fun self(): ConcreteGestureHandlerT = this as ConcreteGestureHandlerT
@@ -159,6 +163,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
159
163
  fun setInteractionController(controller: GestureHandlerInteractionController?): ConcreteGestureHandlerT =
160
164
  applySelf { interactionController = controller }
161
165
 
166
+ fun setMouseButton(mouseButton: Int) = apply {
167
+ this.mouseButton = mouseButton
168
+ }
169
+
162
170
  fun prepare(view: View?, orchestrator: GestureHandlerOrchestrator?) {
163
171
  check(!(this.view != null || this.orchestrator != null)) { "Already prepared or hasn't been reset" }
164
172
  Arrays.fill(trackedPointerIDs, -1)
@@ -167,12 +175,9 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
167
175
  this.view = view
168
176
  this.orchestrator = orchestrator
169
177
 
170
- val decorView = getWindow(view?.context)?.decorView
171
- if (decorView != null) {
172
- val frame = Rect()
173
- decorView.getWindowVisibleDisplayFrame(frame)
174
- windowOffset[0] = frame.left
175
- windowOffset[1] = frame.top
178
+ val content = getActivity(view?.context)?.findViewById<View>(android.R.id.content)
179
+ if (content != null) {
180
+ content.getLocationOnScreen(windowOffset)
176
181
  } else {
177
182
  windowOffset[0] = 0
178
183
  windowOffset[1] = 0
@@ -183,13 +188,13 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
183
188
 
184
189
  protected open fun onPrepare() {}
185
190
 
186
- private fun getWindow(context: Context?): Window? {
187
- if (context == null) return null
188
- if (context is Activity) return context.window
189
- if (context is ContextWrapper) return getWindow(context.baseContext)
190
-
191
- return null
192
- }
191
+ private fun getActivity(context: Context?): Activity? =
192
+ when (context) {
193
+ is ReactContext -> context.currentActivity
194
+ is Activity -> context
195
+ is ContextWrapper -> getActivity(context.baseContext)
196
+ else -> null
197
+ }
193
198
 
194
199
  private fun findNextLocalPointerId(): Int {
195
200
  var localPointerId = 0
@@ -371,6 +376,11 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
371
376
  lastAbsolutePositionY = GestureUtils.getLastPointerY(adaptedTransformedEvent, true)
372
377
  lastEventOffsetX = adaptedTransformedEvent.rawX - adaptedTransformedEvent.x
373
378
  lastEventOffsetY = adaptedTransformedEvent.rawY - adaptedTransformedEvent.y
379
+
380
+ if (sourceEvent.action == MotionEvent.ACTION_DOWN || sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER || sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE) {
381
+ setPointerType(sourceEvent)
382
+ }
383
+
374
384
  if (sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER ||
375
385
  sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE ||
376
386
  sourceEvent.action == MotionEvent.ACTION_HOVER_EXIT
@@ -642,7 +652,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
642
652
  }
643
653
 
644
654
  fun cancel() {
645
- if (state == STATE_ACTIVE || state == STATE_UNDETERMINED || state == STATE_BEGAN) {
655
+ if (state == STATE_ACTIVE || state == STATE_UNDETERMINED || state == STATE_BEGAN || this.isAwaiting) {
646
656
  onCancel()
647
657
  moveToState(STATE_CANCELLED)
648
658
  }
@@ -688,6 +698,46 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
688
698
  protected open fun onReset() {}
689
699
  protected open fun onCancel() {}
690
700
 
701
+ private fun isButtonInConfig(clickedButton: Int): Boolean {
702
+ if (mouseButton == 0) {
703
+ return clickedButton == MotionEvent.BUTTON_PRIMARY
704
+ }
705
+
706
+ return clickedButton and mouseButton != 0
707
+ }
708
+
709
+ protected fun shouldActivateWithMouse(sourceEvent: MotionEvent): Boolean {
710
+ // While using mouse, we get both sets of events, for example ACTION_DOWN and ACTION_BUTTON_PRESS. That's why we want to take actions to only one of them.
711
+ // On API >= 23, we will use events with infix BUTTON, otherwise we use standard action events (like ACTION_DOWN).
712
+
713
+ with(sourceEvent) {
714
+ // To use actionButton, we need API >= 23.
715
+ if (getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
716
+ // While using mouse, we want to ignore default events for touch.
717
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
718
+ return@shouldActivateWithMouse false
719
+ }
720
+
721
+ // We don't want to do anything if wrong button was clicked. If we received event for BUTTON, we have to use actionButton to get which one was clicked.
722
+ if (action != MotionEvent.ACTION_MOVE && !isButtonInConfig(actionButton)) {
723
+ return@shouldActivateWithMouse false
724
+ }
725
+
726
+ // When we receive ACTION_MOVE, we have to check buttonState field.
727
+ if (action == MotionEvent.ACTION_MOVE && !isButtonInConfig(buttonState)) {
728
+ return@shouldActivateWithMouse false
729
+ }
730
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
731
+ // We do not fully support mouse below API 23, so we will ignore BUTTON events.
732
+ if (action == MotionEvent.ACTION_BUTTON_PRESS || action == MotionEvent.ACTION_BUTTON_RELEASE) {
733
+ return@shouldActivateWithMouse false
734
+ }
735
+ }
736
+ }
737
+
738
+ return true
739
+ }
740
+
691
741
  /**
692
742
  * Transforms a point in the coordinate space of the wrapperView (GestureHandlerRootView) to
693
743
  * coordinate space of the view the gesture is attached to.
@@ -708,7 +758,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
708
758
  orchestrator = null
709
759
  Arrays.fill(trackedPointerIDs, -1)
710
760
  trackedPointersIDsCount = 0
711
-
712
761
  trackedPointersCount = 0
713
762
  trackedPointers.fill(null)
714
763
  touchEventType = RNGestureHandlerTouchEvent.EVENT_UNDETERMINED
@@ -721,6 +770,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
721
770
  isWithinBounds = false
722
771
  }
723
772
 
773
+ private fun setPointerType(event: MotionEvent) {
774
+ val pointerIndex = event.actionIndex
775
+
776
+ pointerType = when (event.getToolType(pointerIndex)) {
777
+ MotionEvent.TOOL_TYPE_FINGER -> POINTER_TYPE_TOUCH
778
+ MotionEvent.TOOL_TYPE_STYLUS -> POINTER_TYPE_STYLUS
779
+ MotionEvent.TOOL_TYPE_MOUSE -> POINTER_TYPE_MOUSE
780
+ else -> POINTER_TYPE_OTHER
781
+ }
782
+ }
783
+
724
784
  fun setOnTouchEventListener(listener: OnTouchEventListener?): GestureHandler<*> {
725
785
  onTouchEventListener = listener
726
786
  return this
@@ -763,19 +823,23 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
763
823
  const val ACTION_TYPE_NATIVE_ANIMATED_EVENT = 2
764
824
  const val ACTION_TYPE_JS_FUNCTION_OLD_API = 3
765
825
  const val ACTION_TYPE_JS_FUNCTION_NEW_API = 4
826
+ const val POINTER_TYPE_TOUCH = 0
827
+ const val POINTER_TYPE_STYLUS = 1
828
+ const val POINTER_TYPE_MOUSE = 2
829
+ const val POINTER_TYPE_OTHER = 3
766
830
  private const val MAX_POINTERS_COUNT = 12
767
831
  private lateinit var pointerProps: Array<PointerProperties?>
768
832
  private lateinit var pointerCoords: Array<PointerCoords?>
769
833
  private fun initPointerProps(size: Int) {
770
- var size = size
834
+ var pointerPropsSize = size
771
835
  if (!Companion::pointerProps.isInitialized) {
772
836
  pointerProps = arrayOfNulls(MAX_POINTERS_COUNT)
773
837
  pointerCoords = arrayOfNulls(MAX_POINTERS_COUNT)
774
838
  }
775
- while (size > 0 && pointerProps[size - 1] == null) {
776
- pointerProps[size - 1] = PointerProperties()
777
- pointerCoords[size - 1] = PointerCoords()
778
- size--
839
+ while (pointerPropsSize > 0 && pointerProps[pointerPropsSize - 1] == null) {
840
+ pointerProps[pointerPropsSize - 1] = PointerProperties()
841
+ pointerCoords[pointerPropsSize - 1] = PointerCoords()
842
+ pointerPropsSize--
779
843
  }
780
844
  }
781
845
 
@@ -7,6 +7,7 @@ import android.view.View
7
7
  import android.view.ViewGroup
8
8
  import android.widget.EditText
9
9
  import java.util.*
10
+ import kotlin.collections.HashSet
10
11
 
11
12
  class GestureHandlerOrchestrator(
12
13
  private val wrapperView: ViewGroup,
@@ -22,6 +23,14 @@ class GestureHandlerOrchestrator(
22
23
  private val gestureHandlers = arrayListOf<GestureHandler<*>>()
23
24
  private val awaitingHandlers = arrayListOf<GestureHandler<*>>()
24
25
  private val preparedHandlers = arrayListOf<GestureHandler<*>>()
26
+
27
+ // In `onHandlerStateChange` method we iterate through `awaitingHandlers`, but calling `tryActivate` may modify this list.
28
+ // To avoid `ConcurrentModificationException` we iterate through copy. There is one more problem though - if handler was
29
+ // removed from `awaitingHandlers`, it was still present in copy of original list. This hashset helps us identify which handlers
30
+ // are really inside `awaitingHandlers`.
31
+ // `contains` method on HashSet has O(1) complexity, so calling it inside for loop won't result in O(n^2) (contrary to ArrayList)
32
+ private val awaitingHandlersTags = HashSet<Int>()
33
+
25
34
  private var isHandlingTouch = false
26
35
  private var handlingChangeSemaphore = 0
27
36
  private var finishedHandlersCleanupScheduled = false
@@ -73,16 +82,18 @@ class GestureHandlerOrchestrator(
73
82
  finishedHandlersCleanupScheduled = false
74
83
  }
75
84
 
76
- private fun hasOtherHandlerToWaitFor(handler: GestureHandler<*>): Boolean {
77
- for (otherHandler in gestureHandlers) {
78
- if (!isFinished(otherHandler.state) && shouldHandlerWaitForOther(handler, otherHandler)) {
79
- return true
80
- }
81
- }
82
- return false
83
- }
85
+ private fun hasOtherHandlerToWaitFor(handler: GestureHandler<*>) =
86
+ gestureHandlers.any { !isFinished(it.state) && shouldHandlerWaitForOther(handler, it) }
87
+
88
+ private fun shouldBeCancelledByFinishedHandler(handler: GestureHandler<*>) = gestureHandlers.any { shouldHandlerWaitForOther(handler, it) && it.state == GestureHandler.STATE_END }
84
89
 
85
90
  private fun tryActivate(handler: GestureHandler<*>) {
91
+ // If we are waiting for a gesture that has successfully finished, we should cancel handler
92
+ if (shouldBeCancelledByFinishedHandler(handler)) {
93
+ handler.cancel()
94
+ return
95
+ }
96
+
86
97
  // see if there is anyone else who we need to wait for
87
98
  if (hasOtherHandlerToWaitFor(handler)) {
88
99
  addAwaitingHandler(handler)
@@ -94,34 +105,47 @@ class GestureHandlerOrchestrator(
94
105
  }
95
106
 
96
107
  private fun cleanupAwaitingHandlers() {
97
- awaitingHandlers.removeAll { !it.isAwaiting }
108
+ val awaitingHandlersCopy = awaitingHandlers.toList()
109
+
110
+ for (handler in awaitingHandlersCopy) {
111
+ if (!handler.isAwaiting) {
112
+ awaitingHandlers.remove(handler)
113
+ awaitingHandlersTags.remove(handler.tag)
114
+ }
115
+ }
98
116
  }
99
117
 
100
118
  /*package*/
101
119
  fun onHandlerStateChange(handler: GestureHandler<*>, newState: Int, prevState: Int) {
102
120
  handlingChangeSemaphore += 1
103
121
  if (isFinished(newState)) {
122
+ // We have to loop through copy in order to avoid modifying collection
123
+ // while iterating over its elements
124
+ val currentlyAwaitingHandlers = awaitingHandlers.toList()
125
+
104
126
  // if there were handlers awaiting completion of this handler, we can trigger active state
105
- for (otherHandler in awaitingHandlers) {
106
- if (shouldHandlerWaitForOther(otherHandler, handler)) {
107
- if (newState == GestureHandler.STATE_END) {
108
- // gesture has ended, we need to kill the awaiting handler
109
- otherHandler.cancel()
110
- if (otherHandler.state == GestureHandler.STATE_END) {
111
- // Handle edge case, where discrete gestures end immediately after activation thus
112
- // their state is set to END and when the gesture they are waiting for activates they
113
- // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
114
- // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
115
- otherHandler.dispatchStateChange(
116
- GestureHandler.STATE_CANCELLED,
117
- GestureHandler.STATE_BEGAN
118
- )
119
- }
120
- otherHandler.isAwaiting = false
121
- } else {
122
- // gesture has failed recognition, we may try activating
123
- tryActivate(otherHandler)
127
+ for (otherHandler in currentlyAwaitingHandlers) {
128
+ if (!shouldHandlerWaitForOther(otherHandler, handler) || !awaitingHandlersTags.contains(otherHandler.tag)) {
129
+ continue
130
+ }
131
+
132
+ if (newState == GestureHandler.STATE_END) {
133
+ // gesture has ended, we need to kill the awaiting handler
134
+ otherHandler.cancel()
135
+ if (otherHandler.state == GestureHandler.STATE_END) {
136
+ // Handle edge case, where discrete gestures end immediately after activation thus
137
+ // their state is set to END and when the gesture they are waiting for activates they
138
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
139
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
140
+ otherHandler.dispatchStateChange(
141
+ GestureHandler.STATE_CANCELLED,
142
+ GestureHandler.STATE_BEGAN
143
+ )
124
144
  }
145
+ otherHandler.isAwaiting = false
146
+ } else {
147
+ // gesture has failed recognition, we may try activating
148
+ tryActivate(otherHandler)
125
149
  }
126
150
  }
127
151
  cleanupAwaitingHandlers()
@@ -168,7 +192,6 @@ class GestureHandlerOrchestrator(
168
192
  // Clear all awaiting handlers waiting for the current handler to fail
169
193
  for (otherHandler in awaitingHandlers.reversed()) {
170
194
  if (shouldHandlerBeCancelledBy(otherHandler, handler)) {
171
- otherHandler.cancel()
172
195
  otherHandler.isAwaiting = false
173
196
  }
174
197
  }
@@ -383,6 +406,8 @@ class GestureHandlerOrchestrator(
383
406
  }
384
407
 
385
408
  awaitingHandlers.add(handler)
409
+ awaitingHandlersTags.add(handler.tag)
410
+
386
411
  with(handler) {
387
412
  isAwaiting = true
388
413
  activationIndex = this@GestureHandlerOrchestrator.activationIndex++
@@ -1,6 +1,7 @@
1
1
  package com.swmansion.gesturehandler.core
2
2
 
3
3
  import android.view.MotionEvent
4
+ import kotlin.math.cos
4
5
 
5
6
  object GestureUtils {
6
7
  fun getLastPointerX(event: MotionEvent, averageTouches: Boolean): Float {
@@ -44,4 +45,6 @@ object GestureUtils {
44
45
  event.getY(lastPointerIdx)
45
46
  }
46
47
  }
48
+ fun coneToDeviation(angle: Double): Double =
49
+ cos(Math.toRadians(angle / 2.0))
47
50
  }
@@ -38,6 +38,10 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
38
38
  }
39
39
 
40
40
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
41
+ if (!shouldActivateWithMouse(sourceEvent)) {
42
+ return
43
+ }
44
+
41
45
  if (state == STATE_UNDETERMINED) {
42
46
  previousTime = SystemClock.uptimeMillis()
43
47
  startTime = previousTime
@@ -51,7 +55,7 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
51
55
  activate()
52
56
  }
53
57
  }
54
- if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
58
+ if (sourceEvent.actionMasked == MotionEvent.ACTION_UP || sourceEvent.actionMasked == MotionEvent.ACTION_BUTTON_RELEASE) {
55
59
  handler?.let {
56
60
  it.removeCallbacksAndMessages(null)
57
61
  handler = null