Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Gesture Handler to TurboModule #2354

Merged
merged 18 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FabricExample/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: a80659eb4504ad696295b3e51b90805a97c34129
React-utils: 2e199c0f64d49f8ca4175d878e365d2701ad41f7
ReactCommon: 82a6500a0906815f2e6079d6a3f226bd2f58e61d
RNGestureHandler: 38016feaff9bd5d8282c78ddce37a89b3a1d595b
RNGestureHandler: b028dd5cade762010a72ee9be3afac17a0f72787
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 580401abccf998bc081186108e981602f90e67b2

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.swmansion.gesturehandler;

import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;

public abstract class NativeRNGestureHandlerModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
public static final String NAME = "RNGestureHandlerModule";

public NativeRNGestureHandlerModuleSpec(ReactApplicationContext reactContext) {
super(reactContext);
}

@Override
public @Nonnull String getName() {
return NAME;
}

@DoNotStrip
public abstract void handleSetJSResponder(double tag, boolean blockNativeResponder);

@DoNotStrip
public abstract void handleClearJSResponder();

@DoNotStrip
public abstract void createGestureHandler(String handlerName, double handlerTag, ReadableMap config);

@DoNotStrip
public abstract void attachGestureHandler(double handlerTag, double newView, double actionType);

@DoNotStrip
public abstract void updateGestureHandler(double handlerTag, ReadableMap newConfig);

@DoNotStrip
public abstract void dropGestureHandler(double handlerTag);

@DoNotStrip
public abstract boolean install();

@DoNotStrip
public abstract void flushOperations();
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,81 @@
package com.swmansion.gesturehandler

import com.facebook.react.ReactPackage
import com.facebook.react.TurboReactPackage
import com.facebook.react.ViewManagerOnDemandReactPackage
import com.facebook.react.bridge.ModuleSpec
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.module.model.ReactModuleInfo
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.turbomodule.core.interfaces.TurboModule
import com.facebook.react.uimanager.ViewManager
import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
import com.swmansion.gesturehandler.react.RNGestureHandlerModule
import com.swmansion.gesturehandler.react.RNGestureHandlerRootViewManager

class RNGestureHandlerPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf<NativeModule>(RNGestureHandlerModule(reactContext))
class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPackage {
private val viewManagers: Map<String, ModuleSpec> by lazy {
mapOf(
RNGestureHandlerRootViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec {
RNGestureHandlerRootViewManager()
},
RNGestureHandlerButtonViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec {
RNGestureHandlerButtonViewManager()
}
)
}

override fun createViewManagers(reactContext: ReactApplicationContext) =
listOf<ViewManager<*, *>>(
RNGestureHandlerRootViewManager(),
RNGestureHandlerButtonViewManager()
)

override fun getViewManagerNames(reactContext: ReactApplicationContext?) =
viewManagers.keys.toList()

override fun getViewManagers(reactContext: ReactApplicationContext?): MutableList<ModuleSpec> =
viewManagers.values.toMutableList()

override fun createViewManager(
reactContext: ReactApplicationContext?,
viewManagerName: String?
) = viewManagers[viewManagerName]?.provider?.get() as? ViewManager<*, *>

override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
return if (name == RNGestureHandlerModule.MODULE_NAME) {
RNGestureHandlerModule(reactContext)
} else {
null
}
}

override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
try {
val reactModuleInfoProviderClass =
Class.forName("com.swmansion.gesturehandler.RNGestureHandlerPackage$\$ReactModuleInfoProvider")
return reactModuleInfoProviderClass.newInstance() as ReactModuleInfoProvider
} catch (e: ClassNotFoundException) {
return ReactModuleInfoProvider {
val reactModule: ReactModule = RNGestureHandlerModule::class.java.getAnnotation(ReactModule::class.java)!!

mutableMapOf(
RNGestureHandlerModule.MODULE_NAME to ReactModuleInfo(
reactModule.name,
RNGestureHandlerModule::class.java.name,
reactModule.canOverrideExistingModule,
reactModule.needsEagerInit,
reactModule.hasConstants,
reactModule.isCxxModule,
TurboModule::class.java.isAssignableFrom(RNGestureHandlerModule::class.java)
)
)
}
} catch (e: InstantiationException) {
throw RuntimeException("No ReactModuleInfoProvider for RNGestureHandlerPackage$\$ReactModuleInfoProvider", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("No ReactModuleInfoProvider for RNGestureHandlerPackage$\$ReactModuleInfoProvider", e)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.view.MotionEvent
import com.facebook.react.ReactRootView
import com.facebook.react.bridge.JSApplicationIllegalArgumentException
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
Expand All @@ -17,6 +16,7 @@ import com.facebook.react.uimanager.events.Event
import com.facebook.soloader.SoLoader
import com.swmansion.common.GestureHandlerStateManager
import com.swmansion.gesturehandler.BuildConfig
import com.swmansion.gesturehandler.NativeRNGestureHandlerModuleSpec
import com.swmansion.gesturehandler.ReanimatedEventDispatcher
import com.swmansion.gesturehandler.core.FlingGestureHandler
import com.swmansion.gesturehandler.core.GestureHandler
Expand Down Expand Up @@ -49,7 +49,7 @@ import com.swmansion.gesturehandler.react.eventbuilders.TapGestureHandlerEventDa
@Suppress("DEPRECATION")
@ReactModule(name = RNGestureHandlerModule.MODULE_NAME)
class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
ReactContextBaseJavaModule(reactContext), GestureHandlerStateManager {
NativeRNGestureHandlerModuleSpec(reactContext), GestureHandlerStateManager {
private abstract class HandlerFactory<T : GestureHandler<T>> {
abstract val type: Class<T>
abstract val name: String
Expand Down Expand Up @@ -333,9 +333,8 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
private val reanimatedEventDispatcher = ReanimatedEventDispatcher()
override fun getName() = MODULE_NAME

@ReactMethod
@Suppress("UNCHECKED_CAST")
fun <T : GestureHandler<T>> createGestureHandler(
private fun <T : GestureHandler<T>> createGestureHandlerHelper(
handlerName: String,
handlerTag: Int,
config: ReadableMap,
Expand All @@ -356,7 +355,21 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
}

@ReactMethod
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
fun attachGestureHandler(handlerTag: Int, viewTag: Int, actionType: Int) {
override fun createGestureHandler(
handlerName: String,
handlerTagDouble: Double,
config: ReadableMap,
) {
val handlerTag = handlerTagDouble.toInt()

createGestureHandlerHelper(handlerName, handlerTag, config)
}

@ReactMethod
override fun attachGestureHandler(handlerTagDouble: Double, viewTagDouble: Double, actionTypeDouble: Double) {
val handlerTag = handlerTagDouble.toInt()
val viewTag = viewTagDouble.toInt()
val actionType = actionTypeDouble.toInt()
// We don't have to handle view flattening in any special way since handlers are stored as
// a map: viewTag -> [handler]. If the view with attached handlers was to be flattened
// then that viewTag simply wouldn't be visited when traversing the view hierarchy in the
Expand All @@ -366,9 +379,8 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
}
}

@ReactMethod
@Suppress("UNCHECKED_CAST")
fun <T : GestureHandler<T>> updateGestureHandler(handlerTag: Int, config: ReadableMap) {
private fun <T : GestureHandler<T>> updateGestureHandlerHelper(handlerTag: Int, config: ReadableMap) {
val handler = registry.getHandler(handlerTag) as T?
if (handler != null) {
val factory = findFactoryForHandler(handler)
Expand All @@ -381,19 +393,32 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
}

@ReactMethod
fun dropGestureHandler(handlerTag: Int) {
override fun updateGestureHandler(handlerTagDouble: Double, config: ReadableMap) {
val handlerTag = handlerTagDouble.toInt()

updateGestureHandlerHelper(handlerTag, config)
}

@ReactMethod
override fun dropGestureHandler(handlerTagDouble: Double) {
val handlerTag = handlerTagDouble.toInt()
interactionManager.dropRelationsForHandlerWithTag(handlerTag)
registry.dropHandler(handlerTag)
}

@ReactMethod
fun handleSetJSResponder(viewTag: Int, blockNativeResponder: Boolean) {
override fun handleSetJSResponder(viewTagDouble: Double, blockNativeResponder: Boolean) {
val viewTag = viewTagDouble.toInt()
val rootView = findRootHelperForViewAncestor(viewTag)
rootView?.handleSetJSResponder(viewTag, blockNativeResponder)
}

@ReactMethod
fun handleClearJSResponder() {
override fun handleClearJSResponder() {
}

@ReactMethod
override fun flushOperations() {
}

override fun setGestureHandlerState(handlerTag: Int, newState: Int) {
Expand All @@ -409,16 +434,18 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
}

@ReactMethod(isBlockingSynchronousMethod = true)
fun install(): Boolean {
return try {
SoLoader.loadLibrary("gesturehandler")
val jsContext = reactApplicationContext.javaScriptContextHolder!!
decorateRuntime(jsContext.get())
true
} catch (exception: Exception) {
Log.w("[RNGestureHandler]", "Could not install JSI bindings.")
false
override fun install(): Boolean {
reactApplicationContext.runOnJSQueueThread {
try {
SoLoader.loadLibrary("gesturehandler")
val jsContext = reactApplicationContext.javaScriptContextHolder!!
decorateRuntime(jsContext.get())
} catch (exception: Exception) {
Log.w("[RNGestureHandler]", "Could not install JSI bindings.")
}
}

return true
}

private external fun decorateRuntime(jsiPtr: Long)
Expand Down
4 changes: 2 additions & 2 deletions apple/RNGestureHandlerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@interface RNGestureHandlerManager : NSObject

- (nonnull instancetype)initWithUIManager:(nonnull RCTUIManager *)uiManager
eventDispatcher:(nonnull RCTEventDispatcher *)eventDispatcher;
eventDispatcher:(nonnull id<RCTEventDispatcherProtocol>)eventDispatcher;

- (void)createGestureHandler:(nonnull NSString *)handlerName
tag:(nonnull NSNumber *)handlerTag
Expand All @@ -26,7 +26,7 @@

- (void)dropAllGestureHandlers;

- (void)handleSetJSResponder:(nonnull NSNumber *)viewTag blockNativeResponder:(nonnull NSNumber *)blockNativeResponder;
- (void)handleSetJSResponder:(nonnull NSNumber *)viewTag blockNativeResponder:(BOOL)blockNativeResponder;

- (void)handleClearJSResponder;

Expand Down
11 changes: 6 additions & 5 deletions apple/RNGestureHandlerManager.mm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import "RNGestureHandlerManager.h"

#import <React/RCTComponent.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTModalHostViewController.h>
#import <React/RCTRootContentView.h>
Expand Down Expand Up @@ -52,11 +52,12 @@ @implementation RNGestureHandlerManager {
RCTUIManager *_uiManager;
NSHashTable<RNRootViewGestureRecognizer *> *_rootViewGestureRecognizers;
NSMutableDictionary<NSNumber *, NSNumber *> *_attachRetryCounter;
RCTEventDispatcher *_eventDispatcher;
id<RCTEventDispatcherProtocol> _eventDispatcher;
id _reanimatedModule;
}

- (instancetype)initWithUIManager:(RCTUIManager *)uiManager eventDispatcher:(RCTEventDispatcher *)eventDispatcher
- (instancetype)initWithUIManager:(RCTUIManager *)uiManager
eventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher
{
if ((self = [super init])) {
_uiManager = uiManager;
Expand Down Expand Up @@ -177,9 +178,9 @@ - (void)dropAllGestureHandlers
[_registry dropAllHandlers];
}

- (void)handleSetJSResponder:(NSNumber *)viewTag blockNativeResponder:(NSNumber *)blockNativeResponder
- (void)handleSetJSResponder:(NSNumber *)viewTag blockNativeResponder:(BOOL)blockNativeResponder
{
if ([blockNativeResponder boolValue]) {
if (blockNativeResponder) {
for (RNRootViewGestureRecognizer *recognizer in _rootViewGestureRecognizers) {
[recognizer blockOtherRecognizers];
}
Expand Down
14 changes: 12 additions & 2 deletions apple/RNGestureHandlerModule.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTUIManager.h>

@interface RNGestureHandlerModule : RCTEventEmitter <RCTBridgeModule>
#ifdef RN_FABRIC_ENABLED
#import <rngesturehandler_codegen/rngesturehandler_codegen.h>
#else
#import <React/RCTBridgeModule.h>
#endif

@interface RNGestureHandlerModule : RCTEventEmitter
#ifdef RN_FABRIC_ENABLED
<NativeRNGestureHandlerModuleSpec>
#else
<RCTBridgeModule>
#endif

@end
Loading
Loading