From 9b3861c1095e64e3cfeea416cdcf9f2d58291e33 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Thu, 1 Mar 2018 10:24:19 -0800 Subject: [PATCH] Fix unmount of ReactRootView for Fabric surfaces Reviewed By: fkgozali Differential Revision: D7114865 fbshipit-source-id: f0a1c47c983e610fe0dba3051ed8aa350ac052cc --- Libraries/Renderer/shims/ReactFabric.js | 4 ++ .../src/main/java/com/facebook/react/BUCK | 1 + .../facebook/react/ReactInstanceManager.java | 9 +++- .../react/fabric/FabricUIManagerModule.java | 44 ++++++++++++++++++- .../com/facebook/react/modules/fabric/BUCK | 14 ++++++ .../react/modules/fabric/ReactFabric.java | 18 ++++++++ .../react/uimanager/ReactShadowNodeImpl.java | 2 +- 7 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/fabric/ReactFabric.java diff --git a/Libraries/Renderer/shims/ReactFabric.js b/Libraries/Renderer/shims/ReactFabric.js index 4a396c224..4162ca62f 100644 --- a/Libraries/Renderer/shims/ReactFabric.js +++ b/Libraries/Renderer/shims/ReactFabric.js @@ -9,6 +9,8 @@ */ 'use strict'; +const BatchedBridge = require('BatchedBridge'); + // TODO @sema: Adjust types import type {ReactNativeType} from 'ReactNativeTypes'; @@ -20,4 +22,6 @@ if (__DEV__) { ReactFabric = require('ReactFabric-prod'); } +BatchedBridge.registerCallableModule('ReactFabric', ReactFabric); + module.exports = (ReactFabric: ReactNativeType); diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index 2fabe4a11..9a33c9af4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -27,6 +27,7 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/appregistry:appregistry"), react_native_target("java/com/facebook/react/modules/core:core"), react_native_target("java/com/facebook/react/modules/debug:debug"), + react_native_target("java/com/facebook/react/modules/fabric:fabric"), react_native_target("java/com/facebook/react/modules/debug:interfaces"), react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"), react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 0b24f48db..1ecbd0efd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -71,6 +71,7 @@ import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; import com.facebook.react.modules.appregistry.AppRegistry; +import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.modules.core.ReactChoreographer; @@ -1033,8 +1034,14 @@ public class ReactInstanceManager { CatalystInstance catalystInstance) { Log.d(ReactConstants.TAG, "ReactInstanceManager.detachViewFromInstance()"); UiThreadUtil.assertOnUiThread(); - catalystInstance.getJSModule(AppRegistry.class) + if (rootView.isFabric()) { + catalystInstance.getJSModule(ReactFabric.class) + .unmountComponentAtNodeAndRemoveContainer(rootView.getId()); + } else { + catalystInstance.getJSModule(AppRegistry.class) .unmountApplicationComponentAtRootTag(rootView.getId()); + } + } private void tearDownReactContext(ReactContext reactContext) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java index 57a751600..1cc927c57 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerModule.java @@ -2,6 +2,12 @@ package com.facebook.react.fabric; +import static android.view.View.MeasureSpec.AT_MOST; +import static android.view.View.MeasureSpec.EXACTLY; +import static android.view.View.MeasureSpec.UNSPECIFIED; + +import android.util.Log; +import android.view.View; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.ReactApplicationContext; @@ -235,8 +241,7 @@ public class FabricUIManagerModule implements UIManager { int widthMeasureSpec = rootView.getWidthMeasureSpec(); int heightMeasureSpec = rootView.getHeightMeasureSpec(); - rootShadowNode.setStyleWidthAuto(); - rootShadowNode.setStyleHeightAuto(); + updateRootView(rootShadowNode, widthMeasureSpec, heightMeasureSpec); mRootShadowNodeRegistry.addNode(rootShadowNode); mUIViewOperationQueue.addRootView(rootTag, rootView, themedRootContext); @@ -257,4 +262,39 @@ public class FabricUIManagerModule implements UIManager { return rootNode; } + /** + * Updates the styles of the {@link ReactShadowNode} based on the Measure specs received by + * parameters. + */ + public void updateRootView( + ReactShadowNode rootCSSNode, int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = View.MeasureSpec.getMode(widthMeasureSpec); + int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); + switch (widthMode) { + case EXACTLY: + rootCSSNode.setStyleWidth(widthSize); + break; + case AT_MOST: + rootCSSNode.setStyleMaxWidth(widthSize); + break; + case UNSPECIFIED: + rootCSSNode.setStyleWidthAuto(); + break; + } + + int heightMode = View.MeasureSpec.getMode(heightMeasureSpec); + int heightSize = View.MeasureSpec.getSize(heightMeasureSpec); + switch (heightMode) { + case EXACTLY: + rootCSSNode.setStyleHeight(heightSize); + break; + case AT_MOST: + rootCSSNode.setStyleMaxHeight(heightSize); + break; + case UNSPECIFIED: + rootCSSNode.setStyleHeightAuto(); + break; + } + } + } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK new file mode 100644 index 000000000..e7b5d9a72 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK @@ -0,0 +1,14 @@ +load("//ReactNative:DEFS.bzl", "rn_android_library", "react_native_target") + +rn_android_library( + name = "fabric", + srcs = glob(["**/*.java"]), + provided_deps = [ + ], + visibility = [ + "PUBLIC", + ], + deps = [ + react_native_target("java/com/facebook/react/bridge:bridge"), + ], +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/ReactFabric.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/ReactFabric.java new file mode 100644 index 000000000..888e9bafd --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/ReactFabric.java @@ -0,0 +1,18 @@ +package com.facebook.react.modules.fabric; + +import com.facebook.react.bridge.JavaScriptModule; + +/** + * JS module used to execute Fabric specific methods. + * Note: This is a temporary class that will be replaced when Fabric is fully integrated with the + * rest of the modules. + */ +public interface ReactFabric extends JavaScriptModule { + + /** + * JS method used to unmount Fabric surfaces. + * @param rootTag {@link int} react tag of Root {@link com.facebook.react.uimanager.ReactShadowNode} + */ + void unmountComponentAtNodeAndRemoveContainer(int rootTag); + +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java index 449f85cc5..73ed6bc48 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java @@ -222,7 +222,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode "Tried to add child that already has a parent! Remove it from its parent first."); } if (mChildren == null) { - mChildren = new ArrayList(4); + mChildren = new ArrayList<>(4); } mChildren.add(i, child); child.mParent = this;