From 532afbde6e6ac99767f4f381996c1262689e4b87 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Tue, 30 Apr 2019 15:01:37 -0700 Subject: [PATCH] Add support for Modal in Android Summary: This diff implements Modal for Android in Fabric Reviewed By: JoshuaGross Differential Revision: D15069863 fbshipit-source-id: 4171c9590a4a7a1f4f80cf9b08ea9a9e94b9097a --- .../react/fabric/FabricUIManager.java | 1 + .../views/modal/ReactModalHostManager.java | 14 +++ ReactCommon/fabric/components/modal/BUCK | 109 ++++++++++++++++++ .../modal/ModalHostViewComponentDescriptor.h | 51 ++++++++ .../modal/ModalHostViewShadowNode.cpp | 19 +++ .../modal/ModalHostViewShadowNode.h | 33 ++++++ .../components/modal/ModalHostViewState.cpp | 26 +++++ .../components/modal/ModalHostViewState.h | 45 ++++++++ 8 files changed, 298 insertions(+) create mode 100644 ReactCommon/fabric/components/modal/BUCK create mode 100644 ReactCommon/fabric/components/modal/ModalHostViewComponentDescriptor.h create mode 100644 ReactCommon/fabric/components/modal/ModalHostViewShadowNode.cpp create mode 100644 ReactCommon/fabric/components/modal/ModalHostViewShadowNode.h create mode 100644 ReactCommon/fabric/components/modal/ModalHostViewState.cpp create mode 100644 ReactCommon/fabric/components/modal/ModalHostViewState.h diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 4765f51e3..d25268f41 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -87,6 +87,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { sComponentNames.put("Image", "RCTImageView"); sComponentNames.put("ScrollView", "RCTScrollView"); sComponentNames.put("Slider", "RCTSlider"); + sComponentNames.put("ModalHostView", "RCTModalHostView"); sComponentNames.put("Paragraph", "RCTText"); sComponentNames.put("Text", "RCText"); sComponentNames.put("RawText", "RCTRawText"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java index 283a64f72..6a73f5c7d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java @@ -8,9 +8,14 @@ package com.facebook.react.views.modal; import android.content.DialogInterface; +import android.graphics.Point; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewGroupManager; @@ -102,4 +107,13 @@ public class ReactModalHostManager extends ViewGroupManager super.onAfterUpdateTransaction(view); view.showOrUpdate(); } + + @Override + public void updateState(ReactModalHostView view, StateWrapper stateWrapper) { + Point modalSize = ModalHostHelper.getModalHostSize(view.getContext()); + WritableMap map = new WritableNativeMap(); + map.putDouble("screenWidth", PixelUtil.toDIPFromPixel(modalSize.x)); + map.putDouble("screenHeight", PixelUtil.toDIPFromPixel(modalSize.y)); + stateWrapper.updateState(map); + } } diff --git a/ReactCommon/fabric/components/modal/BUCK b/ReactCommon/fabric/components/modal/BUCK new file mode 100644 index 000000000..94272fdfe --- /dev/null +++ b/ReactCommon/fabric/components/modal/BUCK @@ -0,0 +1,109 @@ +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_debug_preprocessor_flags") +load( + "//tools/build_defs/oss:rn_defs.bzl", + "ANDROID", + "APPLE", + "fb_xplat_cxx_test", + "get_apple_compiler_flags", + "get_apple_inspector_flags", + "react_native_target", + "react_native_xplat_target", + "rn_xplat_cxx_library", + "subdir_glob", +) + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "modal", + srcs = glob( + ["**/*.cpp"], + exclude = glob([ + "tests/**/*.cpp", + "platform/**/*.cpp", + ]), + ), + headers = [], + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "react/components/modal", + ), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbandroid_deps = [ + react_native_target("jni/react/jni:jni"), + ], + fbandroid_exported_headers = subdir_glob( + [ + ("", "*.h"), + ("platform/android", "*.h"), + ], + prefix = "react/components/modal", + ), + fbandroid_headers = glob( + ["platform/android/*.h"], + ), + fbandroid_srcs = glob( + ["platform/android/*.cpp"], + ), + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), + force_static = True, + ios_exported_headers = subdir_glob( + [ + ("", "*.h"), + ("platform/ios", "*.h"), + ], + prefix = "react/components/modal", + ), + macosx_tests_override = [], + platforms = (ANDROID, APPLE), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + tests = [":tests"], + visibility = ["PUBLIC"], + deps = [ + "fbsource//xplat/fbsystrace:fbsystrace", + "fbsource//xplat/folly:headers_only", + "fbsource//xplat/folly:memory", + "fbsource//xplat/folly:molly", + "fbsource//xplat/third-party/glog:glog", + "fbsource//xplat/yoga:yoga", + react_native_xplat_target("fabric/debug:debug"), + react_native_xplat_target("fabric/core:core"), + react_native_xplat_target("fabric/components/image:image"), + react_native_xplat_target("fabric/components/view:view"), + react_native_xplat_target("fabric/graphics:graphics"), + react_native_xplat_target("fabric/imagemanager:imagemanager"), + react_native_xplat_target("fabric/uimanager:uimanager"), + "fbsource//xplat/js/react-native-github:generated_components-rncore", + ], +) + +fb_xplat_cxx_test( + name = "tests", + srcs = glob(["tests/**/*.cpp"]), + headers = glob(["tests/**/*.h"]), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + contacts = ["oncall+react_native@xmail.facebook.com"], + platforms = (ANDROID, APPLE), + deps = [ + "fbsource//xplat/folly:molly", + "fbsource//xplat/third-party/gmock:gtest", + ":modal", + ], +) diff --git a/ReactCommon/fabric/components/modal/ModalHostViewComponentDescriptor.h b/ReactCommon/fabric/components/modal/ModalHostViewComponentDescriptor.h new file mode 100644 index 000000000..a9a574a55 --- /dev/null +++ b/ReactCommon/fabric/components/modal/ModalHostViewComponentDescriptor.h @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Descriptor for component. + */ + +class ModalHostViewComponentDescriptor final + : public ConcreteComponentDescriptor { + public: + ModalHostViewComponentDescriptor(EventDispatcher::Shared eventDispatcher) + : ConcreteComponentDescriptor(eventDispatcher) {} + + void adopt(UnsharedShadowNode shadowNode) const override { + assert(std::dynamic_pointer_cast(shadowNode)); + auto modalShadowNode = + std::static_pointer_cast(shadowNode); + + assert( + std::dynamic_pointer_cast(modalShadowNode)); + auto layoutableShadowNode = + std::static_pointer_cast(modalShadowNode); + + auto state = + std::static_pointer_cast( + shadowNode->getState()); + auto stateData = state->getData(); + + layoutableShadowNode->setSize( + Size{stateData.screenSize.width, stateData.screenSize.height}); + layoutableShadowNode->setPositionType(YGPositionTypeAbsolute); + + ConcreteComponentDescriptor::adopt(shadowNode); + } +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.cpp b/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.cpp new file mode 100644 index 000000000..fd3543f88 --- /dev/null +++ b/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.cpp @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "ModalHostViewShadowNode.h" + +#include +#include + +namespace facebook { +namespace react { + +extern const char ModalHostViewComponentName[] = "ModalHostView"; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.h b/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.h new file mode 100644 index 000000000..e29f31faf --- /dev/null +++ b/ReactCommon/fabric/components/modal/ModalHostViewShadowNode.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +extern const char ModalHostViewComponentName[]; + +/* + * `ShadowNode` for component. + */ +class ModalHostViewShadowNode final : public ConcreteViewShadowNode< + ModalHostViewComponentName, + ModalHostViewProps, + ModalHostViewEventEmitter, + ModalHostViewState> { + public: + using ConcreteViewShadowNode::ConcreteViewShadowNode; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/modal/ModalHostViewState.cpp b/ReactCommon/fabric/components/modal/ModalHostViewState.cpp new file mode 100644 index 000000000..be62de46a --- /dev/null +++ b/ReactCommon/fabric/components/modal/ModalHostViewState.cpp @@ -0,0 +1,26 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "ModalHostViewState.h" +#include + +#ifdef ANDROID +#include +#endif + +namespace facebook { +namespace react { + +#ifdef ANDROID +const folly::dynamic ModalHostViewState::getDynamic() const { + return folly::dynamic::object("screenWidth", screenSize.width)( + "screenHeight", screenSize.height); +} +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/modal/ModalHostViewState.h b/ReactCommon/fabric/components/modal/ModalHostViewState.h new file mode 100644 index 000000000..167ffa22d --- /dev/null +++ b/ReactCommon/fabric/components/modal/ModalHostViewState.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * State for component. + */ +class ModalHostViewState : public StateData { + public: + using Shared = std::shared_ptr; + + ModalHostViewState(){}; + ModalHostViewState(Size screenSize_) : screenSize(screenSize_){}; + virtual ~ModalHostViewState() = default; + +#ifdef ANDROID + ModalHostViewState(folly::dynamic data) + : screenSize(Size{(Float)data["screenWidth"].getDouble(), + (Float)data["screenHeight"].getDouble()}){}; +#endif + + const Size screenSize{}; + +#ifdef ANDROID + virtual const folly::dynamic getDynamic() const override; +#endif + +#pragma mark - Getters +}; + +} // namespace react +} // namespace facebook