diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.java deleted file mode 100644 index cca423b07fd..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.internal.interop; - -import androidx.annotation.Nullable; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.uimanager.events.Event; - -/** - * An {@link Event} class used by the {@link InteropEventEmitter}. This class is just holding the - * event name and the data which is received by the `receiveEvent` method and will be passed over - * the the {@link com.facebook.react.uimanager.events.EventDispatcher} - */ -class InteropEvent extends Event { - - private final String mName; - private final WritableMap mEventData; - - InteropEvent(String name, @Nullable WritableMap eventData, int surfaceId, int viewTag) { - super(surfaceId, viewTag); - mName = name; - mEventData = eventData; - } - - @Override - public String getEventName() { - return mName; - } - - @Override - @VisibleForTesting - public WritableMap getEventData() { - return mEventData; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.kt new file mode 100644 index 00000000000..31c630db641 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.internal.interop + +import com.facebook.react.bridge.WritableMap +import com.facebook.react.uimanager.events.Event + +/** + * An [Event] class used by the [InteropEventEmitter]. This class is just holding the event name and + * the data which is received by the `receiveEvent` method and will be passed over the the + * [com.facebook.react.uimanager.events.EventDispatcher] + */ +class InteropEvent( + @get:JvmName("eventName") val eventName: String, + @get:JvmName("eventData") val eventData: WritableMap?, + surfaceId: Int, + viewTag: Int +) : Event(surfaceId, viewTag) { + override fun getEventName(): String = eventName + + override fun getEventData(): WritableMap? = eventData +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.java deleted file mode 100644 index c2d7c42f586..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.internal.interop; - -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.uimanager.UIManagerHelper; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.events.RCTEventEmitter; - -/** - * A reimplementation of {@link RCTEventEmitter} which is using a {@link EventDispatcher} under the - * hood. - * - *

On Fabric, you're supposed to use {@link EventDispatcher} to dispatch events. However, we - * provide an interop layer for non-Fabric migrated components. - * - *

This instance will be returned if the user is invoking `context.getJsModule(RCTEventEmitter) - * and is providing support for the `receiveEvent` method, so that non-Fabric ViewManagers can - * continue to deliver events also when Fabric is turned on. - */ -public class InteropEventEmitter implements RCTEventEmitter { - - private final ReactContext mReactContext; - - private @Nullable EventDispatcher mEventDispatcherOverride; - - public InteropEventEmitter(ReactContext reactContext) { - mReactContext = reactContext; - } - - @Override - public void receiveEvent(int targetReactTag, String eventName, @Nullable WritableMap eventData) { - EventDispatcher dispatcher; - if (mEventDispatcherOverride != null) { - dispatcher = mEventDispatcherOverride; - } else { - dispatcher = UIManagerHelper.getEventDispatcherForReactTag(mReactContext, targetReactTag); - } - int surfaceId = UIManagerHelper.getSurfaceId(mReactContext); - if (dispatcher != null) { - dispatcher.dispatchEvent(new InteropEvent(eventName, eventData, surfaceId, targetReactTag)); - } - } - - @Override - public void receiveTouches( - String eventName, WritableArray touches, WritableArray changedIndices) { - throw new UnsupportedOperationException( - "EventEmitter#receiveTouches is not supported by the Fabric Interop Layer"); - } - - @VisibleForTesting - void overrideEventDispatcher(EventDispatcher eventDispatcherOverride) { - mEventDispatcherOverride = eventDispatcherOverride; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.kt new file mode 100644 index 00000000000..0946269f8c8 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@file:Suppress("DEPRECATION") // We want to use RCTEventEmitter for interop purposes + +package com.facebook.react.internal.interop + +import com.facebook.react.bridge.ReactContext +import com.facebook.react.bridge.WritableArray +import com.facebook.react.bridge.WritableMap +import com.facebook.react.common.annotations.VisibleForTesting +import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.events.EventDispatcher +import com.facebook.react.uimanager.events.RCTEventEmitter + +/** + * A reimplementation of [RCTEventEmitter] which is using a [EventDispatcher] under the hood. + * + * On Fabric, you're supposed to use [EventDispatcher] to dispatch events. However, we provide an + * interop layer for non-Fabric migrated components. + * + * This instance will be returned if the user is invoking `context.getJsModule(RCTEventEmitter) and + * is providing support for the `receiveEvent` method, so that non-Fabric ViewManagers can continue + * to deliver events also when Fabric is turned on. + */ +class InteropEventEmitter(private val reactContext: ReactContext) : RCTEventEmitter { + private var eventDispatcherOverride: EventDispatcher? = null + + @Deprecated("Deprecated in Java") + override fun receiveEvent(targetReactTag: Int, eventName: String, eventData: WritableMap?) { + val dispatcher: EventDispatcher? = + eventDispatcherOverride + ?: UIManagerHelper.getEventDispatcherForReactTag(reactContext, targetReactTag) + val surfaceId = UIManagerHelper.getSurfaceId(reactContext) + dispatcher?.dispatchEvent(InteropEvent(eventName, eventData, surfaceId, targetReactTag)) + } + + override fun receiveTouches( + eventName: String, + touches: WritableArray, + changedIndices: WritableArray + ) { + throw UnsupportedOperationException( + "EventEmitter#receiveTouches is not supported by the Fabric Interop Layer") + } + + @VisibleForTesting + fun overrideEventDispatcher(eventDispatcherOverride: EventDispatcher?) { + this.eventDispatcherOverride = eventDispatcherOverride + } +} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/internal/interop/InteropEventEmitterTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/internal/interop/InteropEventEmitterTest.kt index 7200a7fab5c..10a71829e6f 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/internal/interop/InteropEventEmitterTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/internal/interop/InteropEventEmitterTest.kt @@ -5,8 +5,11 @@ * LICENSE file in the root directory of this source tree. */ +@file:Suppress("DEPRECATION") // We want to use RCTEventEmitter for interop purposes + package com.facebook.react.internal.interop +import com.facebook.react.bridge.JavaOnlyArray import com.facebook.react.bridge.JavaOnlyMap import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContext @@ -50,8 +53,8 @@ class InteropEventEmitterTest { eventEmitter.receiveEvent(42, "onTest", eventData) - val event = eventDispatcher.getRecordedDispatchedEvents().get(0) as InteropEvent - val dispatchedEventData = event.getEventData() + val event = eventDispatcher.getRecordedDispatchedEvents()[0] as InteropEvent + val dispatchedEventData = event.eventData assertNotNull(dispatchedEventData) assertEquals("indigo", dispatchedEventData!!.getString("color")) } @@ -59,6 +62,6 @@ class InteropEventEmitterTest { @Test(expected = java.lang.UnsupportedOperationException::class) fun receiveTouches_isNotSupported() { val eventEmitter = InteropEventEmitter(reactContext) - eventEmitter.receiveTouches("a touch", null, null) + eventEmitter.receiveTouches("a touch", JavaOnlyArray.of(), JavaOnlyArray.of()) } }