Migrate UIManager interface to Kotlin (#44589)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44589

## Changelog:
[Internal] -

As in the title.

Reviewed By: tdn120

Differential Revision: D57434432

fbshipit-source-id: ce2504d5a27a9e8dd8d8d02b052b6cf9414491ab
This commit is contained in:
Ruslan Shestopalyuk
2024-08-02 07:10:36 -07:00
committed by Facebook GitHub Bot
parent de73e44569
commit 51278d3f30
5 changed files with 170 additions and 174 deletions
@@ -1,162 +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.bridge;
import static com.facebook.infer.annotation.ThreadConfined.UI;
import android.view.View;
import androidx.annotation.AnyThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.facebook.infer.annotation.ThreadConfined;
public interface UIManager extends PerformanceCounter {
/** Registers a new root view. @Deprecated call startSurface instead */
@UiThread
@ThreadConfined(UI)
@Deprecated
<T extends View> int addRootView(final T rootView, WritableMap initialProps);
/** Registers a new root view with width and height. */
@AnyThread
<T extends View> int startSurface(
final T rootView,
final String moduleName,
final WritableMap initialProps,
int widthMeasureSpec,
int heightMeasureSpec);
/**
* Stop a surface from running in JS and clears up native memory usage. Assumes that the native
* View hierarchy has already been cleaned up. Fabric-only.
*/
@AnyThread
void stopSurface(final int surfaceId);
/**
* Updates the layout specs of the RootShadowNode based on the Measure specs received by
* parameters. offsetX and offsetY are the position of the RootView within the screen.
*/
@UiThread
@ThreadConfined(UI)
void updateRootLayoutSpecs(
int rootTag, int widthMeasureSpec, int heightMeasureSpec, int offsetX, int offsetY);
/**
* Dispatches the commandId received by parameter to the view associated with the reactTag. The
* command will be processed in the UIThread.
*
* <p>Receiving commands as ints is deprecated and will be removed in a future release.
*
* <p>Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag {@link int} that identifies the view that will receive this command
* @param commandId {@link int} command id
* @param commandArgs {@link ReadableArray} parameters associated with the command
*/
void dispatchCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs);
/**
* Dispatches the commandId received by parameter to the view associated with the reactTag. The
* command will be processed in the UIThread.
*
* <p>Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag {@link int} that identifies the view that will receive this command
* @param commandId {@link String} command id
* @param commandArgs {@link ReadableArray} parameters associated with the command
*/
void dispatchCommand(int reactTag, String commandId, @Nullable ReadableArray commandArgs);
/**
* @return the {@link EventDispatcher} object that is used by this class.
*/
<T> T getEventDispatcher();
/**
* Used by native animated module to bypass the process of updating the values through the shadow
* view hierarchy. This method will directly update native views, which means that updates for
* layout-related propertied won't be handled properly. Make sure you know what you're doing
* before calling this method :)
*
* @param reactTag {@link int} that identifies the view that will be updated
* @param props {@link ReadableMap} props that should be immediately updated in view
*/
@UiThread
@ThreadConfined(UI)
void synchronouslyUpdateViewOnUIThread(int reactTag, ReadableMap props);
/**
* Dispatch an accessibility event to a view asynchronously.
*
* <p>Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag
* @param eventType
*/
void sendAccessibilityEvent(int reactTag, int eventType);
/**
* Register a {@link UIManagerListener} with this UIManager to receive lifecycle callbacks.
*
* @param listener
*/
void addUIManagerEventListener(UIManagerListener listener);
/**
* Unregister a {@link UIManagerListener} from this UIManager to stop receiving lifecycle
* callbacks.
*
* @param listener
*/
void removeUIManagerEventListener(UIManagerListener listener);
/**
* Resolves a view based on its reactTag. Do not mutate properties on this view that are already
* managed by React, as there are no guarantees this changes will be preserved.
*
* @throws IllegalViewOperationException if tag could not be resolved.
* @param reactTag tag
* @return view if found
*/
View resolveView(int reactTag);
/**
* This method dispatches events from RN Android code to JS. The delivery of this event will not
* be queued in EventDispatcher class.
*
* @param reactTag tag
* @param eventName name of the event
* @param event parameters
*/
@Deprecated
void receiveEvent(int reactTag, String eventName, @Nullable WritableMap event);
/**
* This method dispatches events from RN Android code to JS. The delivery of this event will not
* be queued in EventDispatcher class.
*
* @param surfaceId
* @param reactTag tag
* @param eventName name of the event
* @param event parameters
*/
void receiveEvent(int surfaceId, int reactTag, String eventName, @Nullable WritableMap event);
/** Resolves Direct Event name exposed to JS from the one known to the Native side. */
@Deprecated
@Nullable
String resolveCustomDirectEventName(@Nullable String eventName);
/** This method is called after {@link ReactApplicationContext} has been created. */
void initialize();
/** Called before React Native instance is destroyed. */
void invalidate();
}
@@ -0,0 +1,160 @@
/*
* 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.bridge
import android.view.View
import androidx.annotation.AnyThread
import androidx.annotation.UiThread
import com.facebook.infer.annotation.ThreadConfined
import com.facebook.react.common.annotations.UnstableReactNativeAPI
@OptIn(UnstableReactNativeAPI::class)
public interface UIManager : PerformanceCounter {
/** Registers a new root view. @Deprecated call startSurface instead */
@UiThread
@ThreadConfined(ThreadConfined.UI)
@Deprecated("")
public fun <T : View?> addRootView(rootView: T, initialProps: WritableMap?): Int
/** Registers a new root view with width and height. */
@AnyThread
public fun <T : View?> startSurface(
rootView: T,
moduleName: String,
initialProps: WritableMap?,
widthMeasureSpec: Int,
heightMeasureSpec: Int
): Int
/**
* Stop a surface from running in JS and clears up native memory usage. Assumes that the native
* View hierarchy has already been cleaned up. Fabric-only.
*/
@AnyThread public fun stopSurface(surfaceId: Int)
/**
* Updates the layout specs of the RootShadowNode based on the Measure specs received by
* parameters. offsetX and offsetY are the position of the RootView within the screen.
*/
@UiThread
@ThreadConfined(ThreadConfined.UI)
public fun updateRootLayoutSpecs(
rootTag: Int,
widthMeasureSpec: Int,
heightMeasureSpec: Int,
offsetX: Int,
offsetY: Int
)
/**
* Dispatches the commandId received by parameter to the view associated with the reactTag. The
* command will be processed in the UIThread.
*
* Receiving commands as ints is deprecated and will be removed in a future release.
*
* Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag that identifies the view that will receive this command
* @param commandId command id
* @param commandArgs [ReadableArray] parameters associated with the command
*/
public fun dispatchCommand(reactTag: Int, commandId: Int, commandArgs: ReadableArray?)
/**
* Dispatches the commandId received by parameter to the view associated with the reactTag. The
* command will be processed in the UIThread.
*
* Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag that identifies the view that will receive this command
* @param commandId command id
* @param commandArgs [ReadableArray] parameters associated with the command
*/
public fun dispatchCommand(reactTag: Int, commandId: String, commandArgs: ReadableArray?)
/** @return the [EventDispatcher] object that is used by this class. */
public fun <T> getEventDispatcher(): T
/**
* Used by native animated module to bypass the process of updating the values through the shadow
* view hierarchy. This method will directly update native views, which means that updates for
* layout-related propertied won't be handled properly. Make sure you know what you're doing
* before calling this method :)
*
* @param reactTag that identifies the view that will be updated
* @param props [ReadableMap] props that should be immediately updated in view
*/
@UiThread
@ThreadConfined(ThreadConfined.UI)
public fun synchronouslyUpdateViewOnUIThread(reactTag: Int, props: ReadableMap?)
/**
* Dispatch an accessibility event to a view asynchronously.
*
* Pre-Fabric, this is only called on the Native Module Thread.
*
* @param reactTag
* @param eventType
*/
public fun sendAccessibilityEvent(reactTag: Int, eventType: Int)
/**
* Register a [UIManagerListener] with this UIManager to receive lifecycle callbacks.
*
* @param listener
*/
public fun addUIManagerEventListener(listener: UIManagerListener?)
/**
* Unregister a [UIManagerListener] from this UIManager to stop receiving lifecycle callbacks.
*
* @param listener
*/
public fun removeUIManagerEventListener(listener: UIManagerListener?)
/**
* Resolves a view based on its reactTag. Do not mutate properties on this view that are already
* managed by React, as there are no guarantees this changes will be preserved.
*
* @param reactTag tag
* @return view if found
* @throws IllegalViewOperationException if tag could not be resolved.
*/
public fun resolveView(reactTag: Int): View?
/**
* This method dispatches events from RN Android code to JS. The delivery of this event will not
* be queued in EventDispatcher class.
*
* @param reactTag tag
* @param eventName name of the event
* @param event parameters
*/
@Deprecated("", ReplaceWith("receiveEvent(surfaceId, reactTag, eventName, event)"))
public fun receiveEvent(reactTag: Int, eventName: String, event: WritableMap?)
/**
* This method dispatches events from RN Android code to JS. The delivery of this event will not
* be queued in EventDispatcher class.
*
* @param surfaceId
* @param reactTag tag
* @param eventName name of the event
* @param event parameters
*/
public fun receiveEvent(surfaceId: Int, reactTag: Int, eventName: String, event: WritableMap?)
/** Resolves Direct Event name exposed to JS from the one known to the Native side. */
@Deprecated("") public fun resolveCustomDirectEventName(eventName: String): String?
/** This method is called after [ReactApplicationContext] has been created. */
public fun initialize()
/** Called before React Native instance is destroyed. */
public fun invalidate()
}
@@ -92,7 +92,7 @@ class RootViewTest {
val eventEmitterModuleMock = mock(RCTEventEmitter::class.java)
whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java))
.thenReturn(uiManager)
whenever(uiManager.eventDispatcher).thenReturn(eventDispatcher)
whenever(uiManager.getEventDispatcher()).thenReturn(eventDispatcher)
// RootView IDs is React Native follow the 11, 21, 31, ... progression.
val rootViewId = 11
@@ -87,7 +87,7 @@ class NativeAnimatedNodeTraversalTest {
uiManagerMock = mock(UIManagerModule::class.java)
eventDispatcherMock = mock(EventDispatcher::class.java)
whenever(uiManagerMock.eventDispatcher).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.getEventDispatcher()).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.constants).thenAnswer {
MapBuilder.of("customDirectEventTypes", MapBuilder.newHashMap<Any, Any>())
}
@@ -28,13 +28,14 @@ class FakeUIManager : UIManager, UIBlockViewResolver {
TODO("Not yet implemented")
}
@Deprecated("")
override fun <T : View?> addRootView(rootView: T, initialProps: WritableMap?): Int {
TODO("Not yet implemented")
}
override fun <T : View?> startSurface(
rootView: T,
moduleName: String?,
moduleName: String,
initialProps: WritableMap?,
widthMeasureSpec: Int,
heightMeasureSpec: Int
@@ -60,7 +61,7 @@ class FakeUIManager : UIManager, UIBlockViewResolver {
TODO("Not yet implemented")
}
override fun dispatchCommand(reactTag: Int, commandId: String?, commandArgs: ReadableArray?) {
override fun dispatchCommand(reactTag: Int, commandId: String, commandArgs: ReadableArray?) {
TODO("Not yet implemented")
}
@@ -89,20 +90,17 @@ class FakeUIManager : UIManager, UIBlockViewResolver {
return null
}
override fun receiveEvent(reactTag: Int, eventName: String?, event: WritableMap?) {
@Deprecated("")
override fun receiveEvent(reactTag: Int, eventName: String, event: WritableMap?) {
TODO("Not yet implemented")
}
override fun receiveEvent(
surfaceId: Int,
reactTag: Int,
eventName: String?,
event: WritableMap?
) {
override fun receiveEvent(surfaceId: Int, reactTag: Int, eventName: String, event: WritableMap?) {
TODO("Not yet implemented")
}
override fun resolveCustomDirectEventName(eventName: String?): String? {
@Deprecated("")
override fun resolveCustomDirectEventName(eventName: String): String? {
TODO("Not yet implemented")
}