Skip to content

Commit

Permalink
Migrate MVP SafeAreaView to Fabric
Browse files Browse the repository at this point in the history
Reviewed By: shergin

Differential Revision: D17736209

fbshipit-source-id: e70c309f2599cdcb8f234d96915546032b71d223
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Oct 4, 2019
1 parent ae3f7a7 commit 07fd312
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type NativeProps = $ReadOnly<{|
emulateUnlessSupported?: WithDefault<boolean, false>,
|}>;

export default (codegenNativeComponent<NativeProps>(
'RCTSafeAreaView',
): HostComponent<NativeProps>);
export default (codegenNativeComponent<NativeProps>('SafeAreaView', {
paperComponentName: 'RCTSafeAreaView',
interfaceOnly: true,
}): HostComponent<NativeProps>);
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* 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 <UIKit/UIKit.h>

#import <React/RCTViewComponentView.h>

NS_ASSUME_NONNULL_BEGIN

/**
* UIView class for root <SafeAreaView> component.
*/
@interface RCTSafeAreaViewComponentView : RCTViewComponentView

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* 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 "RCTSafeAreaViewComponentView.h"

#import <react/components/safeareaview/SafeAreaViewComponentDescriptor.h>
#import <react/components/safeareaview/SafeAreaViewState.h>
#import "RCTConversions.h"

using namespace facebook::react;

static UIScrollView *findScrollView(UIView *view, uint recursionDepth = 0)
{
if (recursionDepth >= 3) {
return NULL;
}
if ([view isKindOfClass:[UIScrollView class]]) {
return (UIScrollView *)view;
}

if (view.subviews.count >= 1) {
for (UIView *subview in view.subviews) {
UIScrollView *scrollView = findScrollView(subview.subviews.firstObject, recursionDepth + 1);
if (scrollView) {
return scrollView;
}
}
}

return NULL;
}

@implementation RCTSafeAreaViewComponentView {
SafeAreaViewShadowNode::ConcreteState::Shared _state;
}

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const SafeAreaViewProps>();
_props = defaultProps;
self.clipsToBounds = YES;
}

return self;
}

- (void)layoutSubviews
{
[super layoutSubviews];
UIScrollView *scrollView = findScrollView(self);
if (scrollView && CGSizeEqualToSize(scrollView.bounds.size, self.bounds.size)) {
[scrollView setContentInset:self.safeAreaInsets];
} else {
if (_state != nullptr) {
CGSize size = self.bounds.size;
size.height -= self.safeAreaInsets.bottom;
auto newState = SafeAreaViewState{RCTSizeFromCGSize(size)};
_state->updateState(std::move(newState));
}
}
}

#pragma mark - RCTComponentViewProtocol

- (void)updateState:(facebook::react::State::Shared const &)state
oldState:(facebook::react::State::Shared const &)oldState
{
_state = std::static_pointer_cast<const SafeAreaViewShadowNode::ConcreteState>(state);
}

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<SafeAreaViewComponentDescriptor>();
}

@end
2 changes: 2 additions & 0 deletions React/Fabric/Mounting/RCTComponentViewFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#import "RCTParagraphComponentView.h"
#import "RCTPullToRefreshViewComponentView.h"
#import "RCTRootComponentView.h"
#import "RCTSafeAreaViewComponentView.h"
#import "RCTScrollViewComponentView.h"
#import "RCTSliderComponentView.h"
#import "RCTSwitchComponentView.h"
Expand Down Expand Up @@ -53,6 +54,7 @@ + (RCTComponentViewFactory *)standardComponentViewFactory
[componentViewFactory registerComponentViewClass:[RCTUnimplementedNativeComponentView class]];
[componentViewFactory registerComponentViewClass:[RCTModalHostViewComponentView class]];
[componentViewFactory registerComponentViewClass:[RCTARTSurfaceViewComponentView class]];
[componentViewFactory registerComponentViewClass:[RCTSafeAreaViewComponentView class]];

auto providerRegistry = &componentViewFactory->_providerRegistry;

Expand Down
47 changes: 47 additions & 0 deletions ReactCommon/fabric/components/safeareaview/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load(
"//tools/build_defs/oss:rn_defs.bzl",
"APPLE",
"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 = "safeareaview",
srcs = glob(
["**/*.cpp"],
),
headers = [],
header_namespace = "",
exported_headers = subdir_glob(
[
("", "*.h"),
],
prefix = "react/components/safeareaview",
),
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,
labels = ["supermodule:ios/isolation/infra.react_native"],
platforms = (APPLE),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
visibility = ["PUBLIC"],
deps = [
react_native_xplat_target("fabric/core:core"),
"fbsource//xplat/js/react-native-github:generated_components-rncore",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 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 <react/components/safeareaview/SafeAreaViewShadowNode.h>
#include <react/core/ConcreteComponentDescriptor.h>

namespace facebook {
namespace react {

/*
* Descriptor for <SafeAreaView> component.
*/
class SafeAreaViewComponentDescriptor final
: public ConcreteComponentDescriptor<SafeAreaViewShadowNode> {
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
void adopt(UnsharedShadowNode shadowNode) const override {
assert(std::dynamic_pointer_cast<SafeAreaViewShadowNode>(shadowNode));
auto safeAreaViewShadowNode =
std::static_pointer_cast<SafeAreaViewShadowNode>(shadowNode);

assert(std::dynamic_pointer_cast<YogaLayoutableShadowNode>(
safeAreaViewShadowNode));
auto layoutableShadowNode =
std::static_pointer_cast<YogaLayoutableShadowNode>(
safeAreaViewShadowNode);

auto state =
std::static_pointer_cast<const SafeAreaViewShadowNode::ConcreteState>(
shadowNode->getState());
auto stateData = state->getData();

if (stateData.safeAreaSize.width != 0 &&
stateData.safeAreaSize.height != 0) {
layoutableShadowNode->setSize(
Size{stateData.safeAreaSize.width, stateData.safeAreaSize.height});
layoutableShadowNode->setPositionType(YGPositionTypeAbsolute);
}

ConcreteComponentDescriptor::adopt(shadowNode);
}
};

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* 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 "SafeAreaViewShadowNode.h"

namespace facebook {
namespace react {

extern const char SafeAreaViewComponentName[] = "SafeAreaView";

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 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 <react/components/rncore/EventEmitters.h>
#include <react/components/rncore/Props.h>
#include <react/components/safeareaview/SafeAreaViewState.h>
#include <react/components/view/ConcreteViewShadowNode.h>

namespace facebook {
namespace react {

extern const char SafeAreaViewComponentName[];

/*
* `ShadowNode` for <SafeAreaView> component.
*/
class SafeAreaViewShadowNode final : public ConcreteViewShadowNode<
SafeAreaViewComponentName,
SafeAreaViewProps,
ViewEventEmitter,
SafeAreaViewState> {
using ConcreteViewShadowNode::ConcreteViewShadowNode;
};

} // namespace react
} // namespace facebook
12 changes: 12 additions & 0 deletions ReactCommon/fabric/components/safeareaview/SafeAreaViewState.cpp
Original file line number Diff line number Diff line change
@@ -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 "SafeAreaViewState.h"

namespace facebook {
namespace react {} // namespace react
} // namespace facebook
31 changes: 31 additions & 0 deletions ReactCommon/fabric/components/safeareaview/SafeAreaViewState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* 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 <react/graphics/Geometry.h>

namespace facebook {
namespace react {

/*
* State for <SafeAreaView> component.
*/
class SafeAreaViewState final {
public:
using Shared = std::shared_ptr<const SafeAreaViewState>;

SafeAreaViewState(){};
SafeAreaViewState(Size screenSize_) : safeAreaSize(screenSize_){};

const Size safeAreaSize{};

#pragma mark - Getters
};

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static std::string componentNameByReactViewName(std::string viewName) {

// We need this temporarily for testing purposes until we have proper
// implementation of core components.
if (viewName == "SafeAreaView" || viewName == "ScrollContentView" ||
if (viewName == "ScrollContentView" ||
viewName == "AndroidHorizontalScrollContentView" // Android
) {
return "View";
Expand Down

0 comments on commit 07fd312

Please sign in to comment.