From 21a5be8212ee2e727af5bf56459d163285164703 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 19 Jan 2024 03:47:32 -0800 Subject: [PATCH] Convert InteropEvent and InteropEventEmitter to Kotlin (#42358) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42358 Just converting those two classes to Kotlin as I was going over them. Changelog: [Internal] [Changed] - Convert InteropEvent and InteropEventEmitter to Kotlin Reviewed By: javache Differential Revision: D52869490 fbshipit-source-id: c020f75f26171066d938914ce1d4917f27ff80e7 --- .../react/internal/interop/InteropEvent.java | 41 ------------ .../react/internal/interop/InteropEvent.kt | 27 ++++++++ .../internal/interop/InteropEventEmitter.java | 65 ------------------- .../internal/interop/InteropEventEmitter.kt | 55 ++++++++++++++++ .../interop/InteropEventEmitterTest.kt | 9 ++- 5 files changed, 88 insertions(+), 109 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEvent.kt delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/interop/InteropEventEmitter.kt 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 cca423b07fd474..00000000000000 --- 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 00000000000000..31c630db641e3f --- /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 c2d7c42f586196..00000000000000 --- 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 00000000000000..0946269f8c8668 --- /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 7200a7fab5c425..10a71829e6f236 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()) } }