diff --git a/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.h b/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.h new file mode 100644 index 00000000000..32ef896c854 --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.h @@ -0,0 +1,23 @@ +/** + * 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. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RCTLegacyViewManagerInteropComponentView : RCTViewComponentView + +/** + Returns true for components that are supported by LegacyViewManagerInterop layer, false otherwise. + */ ++ (BOOL)isSupported:(NSString *)componentName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.mm b/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.mm new file mode 100644 index 00000000000..afc621fce9a --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/InteropView/RCTLegacyViewManagerInteropComponentView.mm @@ -0,0 +1,82 @@ +/** + * 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. + */ + +#import "RCTLegacyViewManagerInteropComponentView.h" + +#import +#import + +using namespace facebook::react; + +static std::string propNames(LegacyViewManagerInteropViewProps const &props) +{ + std::string propNames; + for (auto const &prop : props.otherProps) { + propNames += prop.first + ", "; + } + if (propNames.size() > 1) { + propNames.resize(propNames.size() - 2); + } + return propNames; +} + +@implementation RCTLegacyViewManagerInteropComponentView { + UILabel *_label; + LegacyViewManagerInteropShadowNode::ConcreteState::Shared _state; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + + CGRect bounds = self.bounds; + _label = [[UILabel alloc] initWithFrame:bounds]; + _label.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3]; + _label.layoutMargins = UIEdgeInsetsMake(12, 12, 12, 12); + _label.lineBreakMode = NSLineBreakByWordWrapping; + _label.numberOfLines = 0; + _label.textAlignment = NSTextAlignmentCenter; + _label.textColor = [UIColor whiteColor]; + + self.contentView = _label; + } + + return self; +} + ++ (BOOL)isSupported:(NSString *)componentName +{ + static NSSet *supportedComponents = [NSSet new]; + return [supportedComponents containsObject:componentName]; +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState +{ + _state = std::static_pointer_cast(state); +} + +- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask +{ + [super finalizeUpdates:updateMask]; + if (_props && _state) { + const auto &props = *std::static_pointer_cast(_props); + + _label.text = [NSString + stringWithFormat:@"name: %s, props: %s", _state->getData().componentName.c_str(), propNames(props).c_str()]; + } +} + +@end diff --git a/React/Fabric/Mounting/RCTComponentViewFactory.mm b/React/Fabric/Mounting/RCTComponentViewFactory.mm index 902775726bb..ab3f3be3e26 100644 --- a/React/Fabric/Mounting/RCTComponentViewFactory.mm +++ b/React/Fabric/Mounting/RCTComponentViewFactory.mm @@ -8,6 +8,7 @@ #import "RCTComponentViewFactory.h" #import +#import #import #import @@ -17,6 +18,7 @@ #import "RCTARTSurfaceViewComponentView.h" #import "RCTActivityIndicatorViewComponentView.h" #import "RCTImageComponentView.h" +#import "RCTLegacyViewManagerInteropComponentView.h" #import "RCTModalHostViewComponentView.h" #import "RCTParagraphComponentView.h" #import "RCTPullToRefreshViewComponentView.h" @@ -52,6 +54,22 @@ using namespace facebook::react; [componentViewFactory registerComponentViewClass:[RCTModalHostViewComponentView class]]; [componentViewFactory registerComponentViewClass:[RCTARTSurfaceViewComponentView class]]; + auto providerRegistry = &componentViewFactory->_providerRegistry; + + providerRegistry->setComponentDescriptorProviderRequest([providerRegistry, + componentViewFactory](ComponentName requestedComponentName) { + if ([RCTLegacyViewManagerInteropComponentView isSupported:RCTNSStringFromString(requestedComponentName)]) { + auto flavor = std::make_shared(requestedComponentName); + auto componentName = ComponentName{flavor->c_str()}; + auto componentHandle = reinterpret_cast(componentName); + auto constructor = [RCTLegacyViewManagerInteropComponentView componentDescriptorProvider].constructor; + + providerRegistry->add(ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor}); + + componentViewFactory->_componentViewClasses[componentHandle] = [RCTLegacyViewManagerInteropComponentView class]; + } + }); + return componentViewFactory; } diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/BUCK b/ReactCommon/fabric/components/legacyviewmanagerinterop/BUCK new file mode 100644 index 00000000000..4ef5fd9f865 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/BUCK @@ -0,0 +1,59 @@ +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_debug_preprocessor_flags") +load( + "//tools/build_defs/oss:rn_defs.bzl", + "APPLE", + "YOGA_CXX_TARGET", + "get_apple_compiler_flags", + "get_apple_inspector_flags", + "react_native_xplat_target", + "rn_xplat_cxx_library", + "subdir_glob", +) + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "legacyviewmanagerinterop", + srcs = glob( + ["**/*.cpp"], + ), + headers = [], + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "react/components/legacyviewmanagerinterop", + ), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), + force_static = True, + platforms = (APPLE), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + 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", + YOGA_CXX_TARGET, + 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", + ], +) diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.cpp b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.cpp new file mode 100644 index 00000000000..c01fd98c8da --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.cpp @@ -0,0 +1,41 @@ +/** + * 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 "LegacyViewManagerInteropComponentDescriptor.h" +#include "LegacyViewManagerInteropState.h" + +namespace facebook { +namespace react { + +ComponentHandle +LegacyViewManagerInteropComponentDescriptor::getComponentHandle() const { + return reinterpret_cast(getComponentName()); +} + +ComponentName LegacyViewManagerInteropComponentDescriptor::getComponentName() + const { + return std::static_pointer_cast(this->flavor_)->c_str(); +} + +void LegacyViewManagerInteropComponentDescriptor::adopt( + ShadowNode::Unshared shadowNode) const { + ConcreteComponentDescriptor::adopt(shadowNode); + + assert(std::dynamic_pointer_cast( + shadowNode)); + auto legacyViewManagerInteropShadowNode = + std::static_pointer_cast(shadowNode); + + // Storing a component name inside the ShadowNode. + auto state = LegacyViewManagerInteropState{}; + state.componentName = + *std::static_pointer_cast(this->flavor_); + + legacyViewManagerInteropShadowNode->setStateData(std::move(state)); +} +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.h b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.h new file mode 100644 index 00000000000..7d51162a386 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.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 + +namespace facebook { +namespace react { + +class LegacyViewManagerInteropComponentDescriptor final + : public ConcreteComponentDescriptor { + public: + using ConcreteComponentDescriptor::ConcreteComponentDescriptor; + + /* + * Returns `name` and `handle` based on a `flavor`, not on static data from + * `LegacyViewManagerInteropShadowNode`. + */ + ComponentHandle getComponentHandle() const override; + ComponentName getComponentName() const override; + + protected: + void adopt(ShadowNode::Unshared shadowNode) const override; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp new file mode 100644 index 00000000000..91bcceef93b --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp @@ -0,0 +1,15 @@ +/** + * 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. + */ + +namespace facebook { +namespace react { + +extern const char LegacyViewManagerInteropComponentName[] = + "LegacyViewManagerInterop"; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h new file mode 100644 index 00000000000..990605adcd5 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h @@ -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. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +extern const char LegacyViewManagerInteropComponentName[]; + +using LegacyViewManagerInteropShadowNode = ConcreteViewShadowNode< + LegacyViewManagerInteropComponentName, + LegacyViewManagerInteropViewProps, + ViewEventEmitter, + LegacyViewManagerInteropState>; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.cpp b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.cpp new file mode 100644 index 00000000000..8d96214dff0 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.cpp @@ -0,0 +1,12 @@ +/** + * 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 "LegacyViewManagerInteropState.h" + +namespace facebook { +namespace react {} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h new file mode 100644 index 00000000000..ee6708c77b7 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h @@ -0,0 +1,24 @@ +/** + * 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 + +#import + +namespace facebook { +namespace react { + +/* + * State for component. + */ +class LegacyViewManagerInteropState final { + public: + std::string componentName; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp new file mode 100644 index 00000000000..a1bd25ec3b5 --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp @@ -0,0 +1,36 @@ +/** + * 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 "LegacyViewManagerInteropViewProps.h" +#include +#include +#include + +namespace facebook { +namespace react { + +static std::unordered_map convertToMap( + RawProps const &rawProps) { + std::unordered_map map{}; + auto const dynamic = (folly::dynamic)rawProps; + if (dynamic.isObject()) { + for (auto const &t : dynamic.items()) { + if (t.first.isString()) { + map[t.first.asString()] = t.second; + } + } + } + return map; +} + +LegacyViewManagerInteropViewProps::LegacyViewManagerInteropViewProps( + const LegacyViewManagerInteropViewProps &sourceProps, + const RawProps &rawProps) + : ViewProps(sourceProps, rawProps), otherProps(convertToMap(rawProps)) {} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h new file mode 100644 index 00000000000..138d4f89f7a --- /dev/null +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h @@ -0,0 +1,28 @@ +/** + * 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 +#include +#include + +namespace facebook { +namespace react { + +class LegacyViewManagerInteropViewProps final : public ViewProps { + public: + LegacyViewManagerInteropViewProps() = default; + LegacyViewManagerInteropViewProps( + const LegacyViewManagerInteropViewProps &sourceProps, + const RawProps &rawProps); + +#pragma mark - Props + + const std::unordered_map otherProps; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/core/primitives/RawProps.cpp b/ReactCommon/fabric/core/primitives/RawProps.cpp index 8ecab77d5e9..bf8cac2227b 100644 --- a/ReactCommon/fabric/core/primitives/RawProps.cpp +++ b/ReactCommon/fabric/core/primitives/RawProps.cpp @@ -52,7 +52,6 @@ void RawProps::parse(RawPropsParser const &parser) const noexcept { parser.preparse(*this); } -#ifdef ANDROID /* * Deprecated. Do not use. * The support for explicit conversion to `folly::dynamic` is deprecated and @@ -68,7 +67,6 @@ RawProps::operator folly::dynamic() const noexcept { return dynamic_; } } -#endif /* * Returns `true` if the object is empty. diff --git a/ReactCommon/fabric/core/primitives/RawProps.h b/ReactCommon/fabric/core/primitives/RawProps.h index 746f7ed72b9..70bda85c098 100644 --- a/ReactCommon/fabric/core/primitives/RawProps.h +++ b/ReactCommon/fabric/core/primitives/RawProps.h @@ -76,14 +76,12 @@ class RawProps final { void parse(RawPropsParser const &parser) const noexcept; -#ifdef ANDROID /* * Deprecated. Do not use. * The support for explicit conversion to `folly::dynamic` is deprecated and * will be removed as soon Android implementation does not need it. */ explicit operator folly::dynamic() const noexcept; -#endif /* * Returns `true` if the object is empty. diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index 960c9dcde93..5f0e8fbb565 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -8,7 +8,6 @@ #include "ShadowNode.h" #include -#include #include #include