Skip to content

Commit aeed371

Browse files
committed
Merge branch 'main' into @mbert/monorepo
2 parents e593b2e + 170f5fd commit aeed371

14 files changed

Lines changed: 551 additions & 590 deletions

File tree

.github/ISSUE_TEMPLATE/bug-report.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ body:
1111
- Make sure to check whether there are similar issues in the repository
1212
- Make sure to clean cache in your project. Depending on your setup this could be done by:
1313
- `yarn start --reset-cache` or
14-
- `npm start -- --reset-cache` or
14+
- `npm run start -- --reset-cache` or
1515
- `expo start --clear`
1616
1717
- type: markdown
@@ -41,9 +41,9 @@ body:
4141
- type: input
4242
id: repro
4343
attributes:
44-
label: Snack or a link to a repository
44+
label: A link to a [Gist](https://gist.github.com/), an [Expo Snack](https://snack.expo.io/) or a link to a repository based on [this template](https://github.com/react-native-community/reproducer-react-native) that reproduces the bug.
4545
description: |
46-
Please provide a Snack (https://snack.expo.io/) or a link to a repository on GitHub under your username that reproduces the issue.
46+
Please provide code snippet, a Snack or a link to a repository on GitHub under your username that reproduces the issue.
4747
Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve.
4848
Issues without a reproduction are likely to stale.
4949
placeholder: Link to a Snack or a GitHub repository
@@ -55,7 +55,7 @@ body:
5555
attributes:
5656
label: Gesture Handler version
5757
description: What version of react-native-gesture-handler are you using?
58-
placeholder: 2.14.0
58+
placeholder: 2.25.0
5959
validations:
6060
required: true
6161

@@ -64,7 +64,7 @@ body:
6464
attributes:
6565
label: React Native version
6666
description: What version of react-native are you using?
67-
placeholder: 0.73.0
67+
placeholder: 0.79.0
6868
validations:
6969
required: true
7070

@@ -95,28 +95,28 @@ body:
9595
label: JavaScript runtime
9696
description: What runtime is your application using?
9797
options:
98-
- JSC
9998
- Hermes
99+
- JSC
100100
- V8
101101

102102
- type: dropdown
103103
id: workflow
104104
attributes:
105105
label: Workflow
106-
description: How your application is managed? Not sure? Read [this part](https://docs.expo.dev/introduction/managed-vs-bare/) of Expo documentation
106+
description: How your application is managed? Not sure? Read [this part](https://docs.expo.dev/develop/development-builds/introduction/) of Expo documentation.
107107
options:
108108
- React Native (without Expo)
109-
- Expo bare workflow
110-
- Expo managed workflow
109+
- Using Expo Go
110+
- Using Expo Prebuild or an Expo development build
111111

112112
- type: dropdown
113113
id: architecture
114114
attributes:
115115
label: Architecture
116-
description: What React Native architecture your application is running on? Currently, the default architecture on React Native is Paper so if you haven't changed it in your application select this option.
116+
description: What React Native architecture your application is running on? Currently, the New Architecture is enabled by default for every new React Native project.
117117
options:
118-
- Paper (Old Architecture)
119-
- Fabric (New Architecture)
118+
- New Architecture (Fabric)
119+
- Old Architecture (Paper)
120120

121121
- type: dropdown
122122
id: build-type

packages/react-native-gesture-handler/android/build.gradle

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ def resolveReactNativeDirectory() {
3939
}
4040

4141
// Fallback to node resolver for custom directory structures like monorepos.
42-
def reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
42+
def reactNativePackage = file(
43+
providers.exec {
44+
workingDir(rootDir)
45+
commandLine("node", "--print", "require.resolve('react-native/package.json')")
46+
}.standardOutput.asText.get().trim()
47+
)
4348
if (reactNativePackage.exists()) {
4449
return reactNativePackage.parentFile
4550
}

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.swmansion.gesturehandler.core
22

3+
import android.content.Context
34
import android.os.Handler
45
import android.os.Looper
56
import android.view.MotionEvent
67
import android.view.VelocityTracker
8+
import com.facebook.react.bridge.ReadableMap
9+
import com.swmansion.gesturehandler.react.eventbuilders.FlingGestureHandlerEventDataBuilder
710

811
class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
912
var numberOfPointersRequired = DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
@@ -123,6 +126,30 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
123126
event.offsetLocation(-offsetX, -offsetY)
124127
}
125128

129+
class Factory : GestureHandler.Factory<FlingGestureHandler>() {
130+
override val type = FlingGestureHandler::class.java
131+
override val name = "FlingGestureHandler"
132+
133+
override fun create(context: Context?): FlingGestureHandler = FlingGestureHandler()
134+
135+
override fun setConfig(handler: FlingGestureHandler, config: ReadableMap) {
136+
super.setConfig(handler, config)
137+
if (config.hasKey(KEY_NUMBER_OF_POINTERS)) {
138+
handler.numberOfPointersRequired = config.getInt(KEY_NUMBER_OF_POINTERS)
139+
}
140+
if (config.hasKey(KEY_DIRECTION)) {
141+
handler.direction = config.getInt(KEY_DIRECTION)
142+
}
143+
}
144+
145+
override fun createEventBuilder(handler: FlingGestureHandler) = FlingGestureHandlerEventDataBuilder(handler)
146+
147+
companion object {
148+
private const val KEY_NUMBER_OF_POINTERS = "numberOfPointers"
149+
private const val KEY_DIRECTION = "direction"
150+
}
151+
}
152+
126153
companion object {
127154
private const val DEFAULT_MAX_DURATION_MS: Long = 800
128155
private const val DEFAULT_MIN_VELOCITY: Long = 2000

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt

Lines changed: 126 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ import android.view.MotionEvent.PointerProperties
1111
import android.view.View
1212
import com.facebook.react.bridge.Arguments
1313
import com.facebook.react.bridge.ReactContext
14+
import com.facebook.react.bridge.ReadableMap
15+
import com.facebook.react.bridge.ReadableType
1416
import com.facebook.react.bridge.UiThreadUtil
1517
import com.facebook.react.bridge.WritableArray
1618
import com.facebook.react.uimanager.PixelUtil
1719
import com.swmansion.gesturehandler.BuildConfig
1820
import com.swmansion.gesturehandler.RNSVGHitTester
1921
import com.swmansion.gesturehandler.react.RNGestureHandlerTouchEvent
22+
import com.swmansion.gesturehandler.react.eventbuilders.GestureHandlerEventDataBuilder
2023
import java.lang.IllegalStateException
2124
import java.util.*
2225

@@ -36,7 +39,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
3639
var isWithinBounds = false
3740
private set
3841
var isEnabled = true
39-
private set
42+
private set(enabled) {
43+
// Don't cancel handler when not changing the value of the isEnabled, executing it always caused
44+
// handlers to be cancelled on re-render because that's the moment when the config is updated.
45+
// If the enabled prop "changed" from true to true the handler would get cancelled.
46+
if (view != null && isEnabled != enabled) {
47+
// If view is set then handler is in "active" state. In that case we want to "cancel" handler
48+
// when it changes enabled state so that it gets cleared from the orchestrator
49+
UiThreadUtil.runOnUiThread { cancel() }
50+
}
51+
field = enabled
52+
}
4053
var actionType = 0
4154

4255
var changedTouchesPayload: WritableArray? = null
@@ -62,9 +75,9 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
6275

6376
private var lastEventOffsetX = 0f
6477
private var lastEventOffsetY = 0f
65-
private var shouldCancelWhenOutside = false
6678
var numberOfPointers = 0
67-
private set
79+
protected set
80+
protected var shouldCancelWhenOutside = false
6881
protected var orchestrator: GestureHandlerOrchestrator? = null
6982
private var onTouchEventListener: OnTouchEventListener? = null
7083
private var interactionController: GestureHandlerInteractionController? = null
@@ -101,11 +114,12 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
101114
}
102115

103116
open fun resetConfig() {
104-
needsPointerData = false
105-
manualActivation = false
106-
shouldCancelWhenOutside = false
107-
isEnabled = true
108-
hitSlop = null
117+
needsPointerData = DEFAULT_NEEDS_POINTER_DATA
118+
manualActivation = DEFAULT_MANUAL_ACTIVATION
119+
shouldCancelWhenOutside = DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE
120+
isEnabled = DEFAULT_IS_ENABLED
121+
hitSlop = DEFAULT_HIT_SLOP
122+
mouseButton = DEFAULT_MOUSE_BUTTON
109123
}
110124

111125
fun hasCommonPointers(other: GestureHandler<*>): Boolean {
@@ -117,26 +131,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
117131
return false
118132
}
119133

120-
fun setShouldCancelWhenOutside(shouldCancelWhenOutside: Boolean): ConcreteGestureHandlerT = applySelf {
121-
this.shouldCancelWhenOutside = shouldCancelWhenOutside
122-
}
123-
124-
fun setEnabled(enabled: Boolean): ConcreteGestureHandlerT = applySelf {
125-
// Don't cancel handler when not changing the value of the isEnabled, executing it always caused
126-
// handlers to be cancelled on re-render because that's the moment when the config is updated.
127-
// If the enabled prop "changed" from true to true the handler would get cancelled.
128-
if (view != null && isEnabled != enabled) {
129-
// If view is set then handler is in "active" state. In that case we want to "cancel" handler
130-
// when it changes enabled state so that it gets cleared from the orchestrator
131-
UiThreadUtil.runOnUiThread { cancel() }
132-
}
133-
isEnabled = enabled
134-
}
135-
136-
fun setManualActivation(manualActivation: Boolean): ConcreteGestureHandlerT = applySelf {
137-
this.manualActivation = manualActivation
138-
}
139-
140134
fun setHitSlop(
141135
leftPad: Float,
142136
topPad: Float,
@@ -175,10 +169,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
175169
interactionController = controller
176170
}
177171

178-
fun setMouseButton(mouseButton: Int) = apply {
179-
this.mouseButton = mouseButton
180-
}
181-
182172
fun prepare(view: View?, orchestrator: GestureHandlerOrchestrator?) {
183173
check(!(this.view != null || this.orchestrator != null)) {
184174
"Already prepared or hasn't been reset"
@@ -859,7 +849,111 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
859849
val lastPositionInWindowY: Float
860850
get() = lastAbsolutePositionY + lastEventOffsetY - windowOffset[1]
861851

852+
abstract class Factory<T : GestureHandler<T>> {
853+
abstract val type: Class<T>
854+
abstract val name: String
855+
abstract fun create(context: Context?): T
856+
open fun setConfig(handler: T, config: ReadableMap) {
857+
handler.resetConfig()
858+
if (config.hasKey(KEY_SHOULD_CANCEL_WHEN_OUTSIDE)) {
859+
handler.shouldCancelWhenOutside = config.getBoolean(KEY_SHOULD_CANCEL_WHEN_OUTSIDE)
860+
}
861+
if (config.hasKey(KEY_ENABLED)) {
862+
handler.isEnabled = config.getBoolean(KEY_ENABLED)
863+
}
864+
if (config.hasKey(KEY_HIT_SLOP)) {
865+
handleHitSlopProperty(handler, config)
866+
}
867+
if (config.hasKey(KEY_NEEDS_POINTER_DATA)) {
868+
handler.needsPointerData = config.getBoolean(KEY_NEEDS_POINTER_DATA)
869+
}
870+
if (config.hasKey(KEY_MANUAL_ACTIVATION)) {
871+
handler.manualActivation = config.getBoolean(KEY_MANUAL_ACTIVATION)
872+
}
873+
if (config.hasKey(KEY_MOUSE_BUTTON)) {
874+
handler.mouseButton = config.getInt(KEY_MOUSE_BUTTON)
875+
}
876+
}
877+
878+
abstract fun createEventBuilder(handler: T): GestureHandlerEventDataBuilder<T>
879+
880+
companion object {
881+
private const val KEY_SHOULD_CANCEL_WHEN_OUTSIDE = "shouldCancelWhenOutside"
882+
private const val KEY_ENABLED = "enabled"
883+
private const val KEY_NEEDS_POINTER_DATA = "needsPointerData"
884+
private const val KEY_MANUAL_ACTIVATION = "manualActivation"
885+
private const val KEY_MOUSE_BUTTON = "mouseButton"
886+
private const val KEY_HIT_SLOP = "hitSlop"
887+
private const val KEY_HIT_SLOP_LEFT = "left"
888+
private const val KEY_HIT_SLOP_TOP = "top"
889+
private const val KEY_HIT_SLOP_RIGHT = "right"
890+
private const val KEY_HIT_SLOP_BOTTOM = "bottom"
891+
private const val KEY_HIT_SLOP_VERTICAL = "vertical"
892+
private const val KEY_HIT_SLOP_HORIZONTAL = "horizontal"
893+
private const val KEY_HIT_SLOP_WIDTH = "width"
894+
private const val KEY_HIT_SLOP_HEIGHT = "height"
895+
896+
private fun handleHitSlopProperty(handler: GestureHandler<*>, config: ReadableMap) {
897+
if (config.getType(KEY_HIT_SLOP) == ReadableType.Number) {
898+
val hitSlop = PixelUtil.toPixelFromDIP(config.getDouble(KEY_HIT_SLOP))
899+
handler.setHitSlop(
900+
hitSlop,
901+
hitSlop,
902+
hitSlop,
903+
hitSlop,
904+
GestureHandler.HIT_SLOP_NONE,
905+
GestureHandler.HIT_SLOP_NONE,
906+
)
907+
} else {
908+
val hitSlop = config.getMap(KEY_HIT_SLOP)!!
909+
var left = GestureHandler.HIT_SLOP_NONE
910+
var top = GestureHandler.HIT_SLOP_NONE
911+
var right = GestureHandler.HIT_SLOP_NONE
912+
var bottom = GestureHandler.HIT_SLOP_NONE
913+
var width = GestureHandler.HIT_SLOP_NONE
914+
var height = GestureHandler.HIT_SLOP_NONE
915+
if (hitSlop.hasKey(KEY_HIT_SLOP_HORIZONTAL)) {
916+
val horizontalPad = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_HORIZONTAL))
917+
right = horizontalPad
918+
left = right
919+
}
920+
if (hitSlop.hasKey(KEY_HIT_SLOP_VERTICAL)) {
921+
val verticalPad = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_VERTICAL))
922+
bottom = verticalPad
923+
top = bottom
924+
}
925+
if (hitSlop.hasKey(KEY_HIT_SLOP_LEFT)) {
926+
left = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_LEFT))
927+
}
928+
if (hitSlop.hasKey(KEY_HIT_SLOP_TOP)) {
929+
top = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_TOP))
930+
}
931+
if (hitSlop.hasKey(KEY_HIT_SLOP_RIGHT)) {
932+
right = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_RIGHT))
933+
}
934+
if (hitSlop.hasKey(KEY_HIT_SLOP_BOTTOM)) {
935+
bottom = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_BOTTOM))
936+
}
937+
if (hitSlop.hasKey(KEY_HIT_SLOP_WIDTH)) {
938+
width = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_WIDTH))
939+
}
940+
if (hitSlop.hasKey(KEY_HIT_SLOP_HEIGHT)) {
941+
height = PixelUtil.toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_HEIGHT))
942+
}
943+
handler.setHitSlop(left, top, right, bottom, width, height)
944+
}
945+
}
946+
}
947+
}
948+
862949
companion object {
950+
private const val DEFAULT_NEEDS_POINTER_DATA = false
951+
private const val DEFAULT_MANUAL_ACTIVATION = false
952+
private const val DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE = false
953+
private const val DEFAULT_IS_ENABLED = true
954+
private val DEFAULT_HIT_SLOP = null
955+
private const val DEFAULT_MOUSE_BUTTON = 0
956+
863957
const val STATE_UNDETERMINED = 0
864958
const val STATE_FAILED = 1
865959
const val STATE_BEGAN = 2

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.swmansion.gesturehandler.core
22

3+
import android.content.Context
34
import android.os.Handler
45
import android.os.Looper
56
import android.view.MotionEvent
67
import android.view.View
78
import android.view.ViewGroup
89
import com.swmansion.gesturehandler.react.RNGestureHandlerRootHelper
910
import com.swmansion.gesturehandler.react.RNViewConfigurationHelper
11+
import com.swmansion.gesturehandler.react.eventbuilders.HoverGestureHandlerEventDataBuilder
1012

1113
class HoverGestureHandler : GestureHandler<HoverGestureHandler>() {
1214
private var handler: Handler? = null
@@ -135,6 +137,15 @@ class HoverGestureHandler : GestureHandler<HoverGestureHandler>() {
135137
}
136138
}
137139

140+
class Factory : GestureHandler.Factory<HoverGestureHandler>() {
141+
override val type = HoverGestureHandler::class.java
142+
override val name = "HoverGestureHandler"
143+
144+
override fun create(context: Context?): HoverGestureHandler = HoverGestureHandler()
145+
146+
override fun createEventBuilder(handler: HoverGestureHandler) = HoverGestureHandlerEventDataBuilder(handler)
147+
}
148+
138149
companion object {
139150
private val viewConfigHelper = RNViewConfigurationHelper()
140151
}

0 commit comments

Comments
 (0)