diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 8a40af852d760f..2d2ca4806b9b4e 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -6209,21 +6209,19 @@ public class com/facebook/react/views/modal/ModalHostShadowNode$$PropsSetter : c public fun setProperty (Lcom/facebook/react/views/modal/ModalHostShadowNode;Ljava/lang/String;Ljava/lang/Object;)V } -public class com/facebook/react/views/modal/ReactModalHostManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/ModalHostViewManagerInterface { +public final class com/facebook/react/views/modal/ReactModalHostManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/ModalHostViewManagerInterface { + public static final field Companion Lcom/facebook/react/views/modal/ReactModalHostManager$Companion; public static final field REACT_CLASS Ljava/lang/String; public fun ()V - protected synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V - protected fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/modal/ReactModalHostView;)V + public synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V public fun createShadowNodeInstance ()Lcom/facebook/react/uimanager/LayoutShadowNode; public synthetic fun createShadowNodeInstance ()Lcom/facebook/react/uimanager/ReactShadowNode; - protected synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View; - protected fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/modal/ReactModalHostView; + public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View; public fun getDelegate ()Lcom/facebook/react/uimanager/ViewManagerDelegate; public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map; public fun getName ()Ljava/lang/String; public fun getShadowNodeClass ()Ljava/lang/Class; - protected synthetic fun onAfterUpdateTransaction (Landroid/view/View;)V - protected fun onAfterUpdateTransaction (Lcom/facebook/react/views/modal/ReactModalHostView;)V + public synthetic fun onAfterUpdateTransaction (Landroid/view/View;)V public synthetic fun onDropViewInstance (Landroid/view/View;)V public fun onDropViewInstance (Lcom/facebook/react/views/modal/ReactModalHostView;)V public synthetic fun setAnimated (Landroid/view/View;Z)V @@ -6255,6 +6253,9 @@ public class com/facebook/react/views/modal/ReactModalHostManager$$PropsSetter : public fun setProperty (Lcom/facebook/react/views/modal/ReactModalHostManager;Lcom/facebook/react/views/modal/ReactModalHostView;Ljava/lang/String;Ljava/lang/Object;)V } +public final class com/facebook/react/views/modal/ReactModalHostManager$Companion { +} + public final class com/facebook/react/views/modal/ReactModalHostView : android/view/ViewGroup, com/facebook/react/bridge/LifecycleEventListener { public fun (Lcom/facebook/react/uimanager/ThemedReactContext;)V public fun addChildrenForAccessibility (Ljava/util/ArrayList;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java deleted file mode 100644 index 6838b210def92f..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java +++ /dev/null @@ -1,174 +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.views.modal; - -import android.graphics.Point; -import androidx.annotation.Nullable; -import com.facebook.infer.annotation.Nullsafe; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ReactStylesDiffMap; -import com.facebook.react.uimanager.StateWrapper; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerHelper; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.ViewManagerDelegate; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.viewmanagers.ModalHostViewManagerDelegate; -import com.facebook.react.viewmanagers.ModalHostViewManagerInterface; -import java.util.HashMap; -import java.util.Map; - -/** View manager for {@link ReactModalHostView} components. */ -@Nullsafe(Nullsafe.Mode.LOCAL) -@ReactModule(name = ReactModalHostManager.REACT_CLASS) -public class ReactModalHostManager extends ViewGroupManager - implements ModalHostViewManagerInterface { - - public static final String REACT_CLASS = "RCTModalHostView"; - - private final ViewManagerDelegate mDelegate; - - public ReactModalHostManager() { - mDelegate = new ModalHostViewManagerDelegate<>(this); - } - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - protected ReactModalHostView createViewInstance(ThemedReactContext reactContext) { - return new ReactModalHostView(reactContext); - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - return new ModalHostShadowNode(); - } - - @Override - public Class getShadowNodeClass() { - return ModalHostShadowNode.class; - } - - @Override - public void onDropViewInstance(ReactModalHostView view) { - super.onDropViewInstance(view); - view.onDropInstance(); - } - - @Override - @ReactProp(name = "animationType") - public void setAnimationType(ReactModalHostView view, @Nullable String animationType) { - if (animationType != null) { - view.setAnimationType(animationType); - } - } - - @Override - @ReactProp(name = "transparent") - public void setTransparent(ReactModalHostView view, boolean transparent) { - view.setTransparent(transparent); - } - - @Override - @ReactProp(name = "statusBarTranslucent") - public void setStatusBarTranslucent(ReactModalHostView view, boolean statusBarTranslucent) { - view.setStatusBarTranslucent(statusBarTranslucent); - } - - @Override - @ReactProp(name = "hardwareAccelerated") - public void setHardwareAccelerated(ReactModalHostView view, boolean hardwareAccelerated) { - view.setHardwareAccelerated(hardwareAccelerated); - } - - @Override - @ReactProp(name = "visible") - public void setVisible(ReactModalHostView view, boolean visible) { - // iOS only - } - - @Override - @ReactProp(name = "presentationStyle") - public void setPresentationStyle(ReactModalHostView view, @Nullable String value) {} - - @Override - @ReactProp(name = "animated") - public void setAnimated(ReactModalHostView view, boolean value) {} - - @Override - @ReactProp(name = "supportedOrientations") - public void setSupportedOrientations(ReactModalHostView view, @Nullable ReadableArray value) {} - - @Override - @ReactProp(name = "identifier") - public void setIdentifier(ReactModalHostView view, int value) {} - - @Override - protected void addEventEmitters( - final ThemedReactContext reactContext, final ReactModalHostView view) { - final EventDispatcher dispatcher = - UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId()); - if (dispatcher != null) { - view.setOnRequestCloseListener( - dialog -> - dispatcher.dispatchEvent( - new RequestCloseEvent(UIManagerHelper.getSurfaceId(reactContext), view.getId()))); - view.setOnShowListener( - dialog -> - dispatcher.dispatchEvent( - new ShowEvent(UIManagerHelper.getSurfaceId(reactContext), view.getId()))); - view.setEventDispatcher(dispatcher); - } - } - - @Override - public Map getExportedCustomDirectEventTypeConstants() { - @Nullable - Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); - Map eventTypeConstants = - baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; - eventTypeConstants.putAll( - MapBuilder.builder() - .put(RequestCloseEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRequestClose")) - .put(ShowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShow")) - // iOS only - .put("topDismiss", MapBuilder.of("registrationName", "onDismiss")) - // iOS only - .put("topOrientationChange", MapBuilder.of("registrationName", "onOrientationChange")) - .build()); - return eventTypeConstants; - } - - @Override - protected void onAfterUpdateTransaction(ReactModalHostView view) { - super.onAfterUpdateTransaction(view); - view.showOrUpdate(); - } - - @Override - @Nullable - public Object updateState( - ReactModalHostView view, ReactStylesDiffMap props, StateWrapper stateWrapper) { - view.setStateWrapper(stateWrapper); - Point modalSize = ModalHostHelper.getModalHostSize(view.getContext()); - view.updateState(modalSize.x, modalSize.y); - return null; - } - - @Override - public ViewManagerDelegate getDelegate() { - return mDelegate; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt new file mode 100644 index 00000000000000..7bb4bc2ae98971 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt @@ -0,0 +1,149 @@ +/* + * 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.views.modal + +import android.content.DialogInterface.OnShowListener +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.common.MapBuilder +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.LayoutShadowNode +import com.facebook.react.uimanager.ReactStylesDiffMap +import com.facebook.react.uimanager.StateWrapper +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.ViewGroupManager +import com.facebook.react.uimanager.ViewManagerDelegate +import com.facebook.react.uimanager.annotations.ReactProp +import com.facebook.react.viewmanagers.ModalHostViewManagerDelegate +import com.facebook.react.viewmanagers.ModalHostViewManagerInterface +import com.facebook.react.views.modal.ModalHostHelper.getModalHostSize +import com.facebook.react.views.modal.ReactModalHostView.OnRequestCloseListener + +/** View manager for [ReactModalHostView] components. */ +@ReactModule(name = ReactModalHostManager.REACT_CLASS) +public class ReactModalHostManager : + ViewGroupManager(), ModalHostViewManagerInterface { + private val delegate: ViewManagerDelegate = ModalHostViewManagerDelegate(this) + + public override fun getName(): String = REACT_CLASS + + protected override fun createViewInstance(reactContext: ThemedReactContext): ReactModalHostView = + ReactModalHostView(reactContext) + + public override fun createShadowNodeInstance(): LayoutShadowNode = ModalHostShadowNode() + + public override fun getShadowNodeClass(): Class = + ModalHostShadowNode::class.java + + public override fun onDropViewInstance(view: ReactModalHostView) { + super.onDropViewInstance(view) + view.onDropInstance() + } + + @ReactProp(name = "animationType") + public override fun setAnimationType(view: ReactModalHostView, animationType: String?) { + if (animationType != null) { + view.animationType = animationType + } + } + + @ReactProp(name = "transparent") + public override fun setTransparent(view: ReactModalHostView, transparent: Boolean) { + view.transparent = transparent + } + + @ReactProp(name = "statusBarTranslucent") + public override fun setStatusBarTranslucent( + view: ReactModalHostView, + statusBarTranslucent: Boolean + ) { + view.statusBarTranslucent = statusBarTranslucent + } + + @ReactProp(name = "hardwareAccelerated") + public override fun setHardwareAccelerated( + view: ReactModalHostView, + hardwareAccelerated: Boolean + ) { + view.hardwareAccelerated = hardwareAccelerated + } + + @ReactProp(name = "visible") + public override fun setVisible(view: ReactModalHostView, visible: Boolean) { + // iOS only + } + + @ReactProp(name = "presentationStyle") + public override fun setPresentationStyle(view: ReactModalHostView, value: String?): Unit = Unit + + @ReactProp(name = "animated") + public override fun setAnimated(view: ReactModalHostView, value: Boolean): Unit = Unit + + @ReactProp(name = "supportedOrientations") + public override fun setSupportedOrientations( + view: ReactModalHostView, + value: ReadableArray? + ): Unit = Unit + + @ReactProp(name = "identifier") + public override fun setIdentifier(view: ReactModalHostView, value: Int): Unit = Unit + + protected override fun addEventEmitters( + reactContext: ThemedReactContext, + view: ReactModalHostView + ) { + val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id) + if (dispatcher != null) { + view.onRequestCloseListener = OnRequestCloseListener { + dispatcher.dispatchEvent( + RequestCloseEvent(UIManagerHelper.getSurfaceId(reactContext), view.id)) + } + view.onShowListener = OnShowListener { + dispatcher.dispatchEvent(ShowEvent(UIManagerHelper.getSurfaceId(reactContext), view.id)) + } + view.eventDispatcher = dispatcher + } + } + + public override fun getExportedCustomDirectEventTypeConstants(): Map = + (super.getExportedCustomDirectEventTypeConstants() ?: mutableMapOf()).apply { + putAll( + MapBuilder.builder() + .put( + RequestCloseEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onRequestClose")) + .put(ShowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShow")) // iOS only + .put("topDismiss", MapBuilder.of("registrationName", "onDismiss")) // iOS only + .put( + "topOrientationChange", + MapBuilder.of("registrationName", "onOrientationChange")) + .build()) + } + + protected override fun onAfterUpdateTransaction(view: ReactModalHostView) { + super.onAfterUpdateTransaction(view) + view.showOrUpdate() + } + + public override fun updateState( + view: ReactModalHostView, + props: ReactStylesDiffMap, + stateWrapper: StateWrapper + ): Any? { + view.stateWrapper = stateWrapper + val modalSize = getModalHostSize(view.context) + view.updateState(modalSize.x, modalSize.y) + return null + } + + public override fun getDelegate(): ViewManagerDelegate = delegate + + public companion object { + public const val REACT_CLASS: String = "RCTModalHostView" + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt index 0596deb209a53c..05ea08a5f22576 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt @@ -373,7 +373,7 @@ public class ReactModalHostView(context: ThemedReactContext) : // This listener is called when the user presses KeyEvent.KEYCODE_BACK // An event is then passed to JS which can either close or not close the Modal by setting the // visible property - public interface OnRequestCloseListener { + public fun interface OnRequestCloseListener { public fun onRequestClose(dialog: DialogInterface?) }