iOS: Support <ActivityIndicator> component

Summary: Setup for using <ActivityIndicator> component in Fabric.

Reviewed By: shergin

Differential Revision: D8107528

fbshipit-source-id: e3ba46d1538f5d5a2fa6f75639caaaa51156c452
This commit is contained in:
Kevin Gozali 2018-05-23 10:03:41 -07:00 committed by Facebook Github Bot
parent 7014a30baa
commit 8bfe78c723
14 changed files with 382 additions and 8 deletions

View File

@ -23,6 +23,7 @@ PODS:
- React/Core
- React/RCTWebSocket
- React/fabric (1000.0.0):
- React/fabric/activityindicator (= 1000.0.0)
- React/fabric/attributedstring (= 1000.0.0)
- React/fabric/core (= 1000.0.0)
- React/fabric/debug (= 1000.0.0)
@ -32,6 +33,8 @@ PODS:
- React/fabric/textlayoutmanager (= 1000.0.0)
- React/fabric/uimanager (= 1000.0.0)
- React/fabric/view (= 1000.0.0)
- React/fabric/activityindicator (1000.0.0):
- Folly (= 2016.10.31.00)
- React/fabric/attributedstring (1000.0.0):
- Folly (= 2016.10.31.00)
- React/fabric/core (1000.0.0):
@ -141,7 +144,7 @@ SPEC CHECKSUMS:
DoubleConversion: a9706f16e388b53ff12cca34473428ee29746a26
Folly: c89ac2d5c6ab169cd7397ef27485c44f35f742c7
glog: 3931855c9cc99c3fab1355fc162fe369162d8183
React: 81df86644d0bca489723c964b33b005901ebfb3b
React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
PODFILE CHECKSUM: 30aa63dcdbb3546a2bacdfd4e005bcca50c9b55c

View File

@ -135,6 +135,15 @@ Pod::Spec.new do |s|
end
s.subspec "fabric" do |ss|
ss.subspec "activityindicator" do |sss|
sss.dependency "Folly", folly_version
sss.compiler_flags = folly_compiler_flags
sss.source_files = "ReactCommon/fabric/activityindicator/**/*.{cpp,h}"
sss.exclude_files = "**/tests/*"
sss.header_dir = "fabric/activityindicator"
sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\"" }
end
ss.subspec "attributedstring" do |sss|
sss.dependency "Folly", folly_version
sss.compiler_flags = folly_compiler_flags

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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 <ShimmeringView> component.
*/
@interface RCTActivityIndicatorViewComponentView : RCTViewComponentView
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,84 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTActivityIndicatorViewComponentView.h"
#import <fabric/activityindicator/ActivityIndicatorViewProps.h>
using namespace facebook::react;
static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const ActivityIndicatorViewSize &size) {
switch (size) {
case ActivityIndicatorViewSize::Small:
return UIActivityIndicatorViewStyleWhite;
case ActivityIndicatorViewSize::Large:
return UIActivityIndicatorViewStyleWhiteLarge;
}
}
@implementation RCTActivityIndicatorViewComponentView {
UIActivityIndicatorView *_activityIndicatorView;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds];
_activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
auto &&defaultProps = ActivityIndicatorViewProps();
if (defaultProps.animating) {
[_activityIndicatorView startAnimating];
} else {
[_activityIndicatorView stopAnimating];
}
_activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps.color.get()];
_activityIndicatorView.hidesWhenStopped = defaultProps.hidesWhenStopped;
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps.size);
[self addSubview:_activityIndicatorView];
}
return self;
}
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{
if (!oldProps) {
oldProps = _props ?: std::make_shared<ActivityIndicatorViewProps>();
}
_props = props;
[super updateProps:props oldProps:oldProps];
auto oldViewProps = *std::dynamic_pointer_cast<const ActivityIndicatorViewProps>(oldProps);
auto newViewProps = *std::dynamic_pointer_cast<const ActivityIndicatorViewProps>(props);
if (oldViewProps.animating != newViewProps.animating) {
if (newViewProps.animating) {
[_activityIndicatorView startAnimating];
} else {
[_activityIndicatorView stopAnimating];
}
}
if (oldViewProps.color.get() != newViewProps.color.get()) {
_activityIndicatorView.color = [UIColor colorWithCGColor:newViewProps.color.get()];
}
// TODO: This prop should be deprecated.
if (oldViewProps.hidesWhenStopped != newViewProps.hidesWhenStopped) {
_activityIndicatorView.hidesWhenStopped = newViewProps.hidesWhenStopped;
}
if (oldViewProps.size != newViewProps.size) {
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(newViewProps.size);
}
}
@end

View File

@ -0,0 +1,19 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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 <fabric/activityindicator/ActivityIndicatorViewShadowNode.h>
#include <fabric/core/ConcreteComponentDescriptor.h>
namespace facebook {
namespace react {
using ActivityIndicatorViewComponentDescriptor = ConcreteComponentDescriptor<ActivityIndicatorViewShadowNode>;
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fabric/activityindicator/ActivityIndicatorViewProps.h>
#include <fabric/activityindicator/conversions.h>
#include <fabric/core/propsConversions.h>
namespace facebook {
namespace react {
ActivityIndicatorViewProps::ActivityIndicatorViewProps(const ActivityIndicatorViewProps &sourceProps, const RawProps &rawProps):
ViewProps(sourceProps, rawProps),
animating(convertRawProp(rawProps, "animating", sourceProps.animating)),
color(convertRawProp(rawProps, "color", sourceProps.color)),
hidesWhenStopped(convertRawProp(rawProps, "hidesWhenStopped", sourceProps.hidesWhenStopped)),
size(convertRawProp(rawProps, "size", sourceProps.size)) {}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fabric/activityindicator/primitives.h>
#include <fabric/graphics/Color.h>
#include <fabric/view/ViewProps.h>
namespace facebook {
namespace react {
// TODO (T28334063): Consider for codegen.
class ActivityIndicatorViewProps final:
public ViewProps {
public:
ActivityIndicatorViewProps() = default;
ActivityIndicatorViewProps(const ActivityIndicatorViewProps &sourceProps, const RawProps &rawProps);
#pragma mark - Props
const bool animating {true};
const SharedColor color {colorFromComponents({153/255.0, 153/255.0, 153/255.0, 1.0})}; // #999999
const bool hidesWhenStopped {true};
const ActivityIndicatorViewSize size {ActivityIndicatorViewSize::Small};
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fabric/activityindicator/ActivityIndicatorViewShadowNode.h>
namespace facebook {
namespace react {
ComponentName ActivityIndicatorViewShadowNode::getComponentName() const {
return ComponentName("ActivityIndicatorView");
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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 <fabric/activityindicator/ActivityIndicatorViewProps.h>
#include <fabric/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
/*
* `ShadowNode` for <ActivityIndicatorView> component.
*/
class ActivityIndicatorViewShadowNode final:
public ConcreteViewShadowNode<ActivityIndicatorViewProps> {
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,78 @@
load("//configurations/buck/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_application_ios_flags", "get_debug_preprocessor_flags")
load("//ReactNative:DEFS.bzl", "ANDROID", "APPLE", "IS_OSS_BUILD", "get_apple_inspector_flags", "react_native_xplat_target", "rn_xplat_cxx_library")
APPLE_COMPILER_FLAGS = []
if not IS_OSS_BUILD:
load("@xplat//configurations/buck/apple:flag_defs.bzl", "flags", "get_static_library_ios_flags")
APPLE_COMPILER_FLAGS = flags.get_flag_value(get_static_library_ios_flags(), "compiler_flags")
rn_xplat_cxx_library(
name = "activityindicator",
srcs = glob(
["**/*.cpp"],
exclude = glob(["tests/**/*.cpp"]),
),
headers = [],
header_namespace = "",
exported_headers = subdir_glob(
[
("", "*.h"),
],
prefix = "fabric/activityindicator",
),
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(),
fbobjc_tests = [
":tests",
],
macosx_tests_override = [],
platforms = (ANDROID, APPLE),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
tests = [],
visibility = ["PUBLIC"],
deps = [
"xplat//fbsystrace:fbsystrace",
"xplat//folly:headers_only",
"xplat//folly:memory",
"xplat//folly:molly",
"xplat//third-party/glog:glog",
"xplat//yoga:yoga",
react_native_xplat_target("fabric/debug:debug"),
react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/graphics:graphics"),
react_native_xplat_target("fabric/view:view"),
],
)
if not IS_OSS_BUILD:
load("@xplat//build_defs:fb_xplat_cxx_test.bzl", "fb_xplat_cxx_test")
fb_xplat_cxx_test(
name = "tests",
srcs = glob(["tests/**/*.cpp"]),
headers = glob(["tests/**/*.h"]),
contacts = ["oncall+react_native@xmail.facebook.com"],
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
platforms = APPLE,
deps = [
"xplat//folly:molly",
"xplat//third-party/gmock:gtest",
":activityindicator",
],
)

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* 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 <fabric/activityindicator/primitives.h>
#include <folly/dynamic.h>
namespace facebook {
namespace react {
inline void fromDynamic(const folly::dynamic &value, ActivityIndicatorViewSize &result) {
auto string = value.asString();
if (string == "large") { result = ActivityIndicatorViewSize::Large; return; }
if (string == "small") { result = ActivityIndicatorViewSize::Small; return; }
abort();
}
inline std::string toString(const ActivityIndicatorViewSize &value) {
switch (value) {
case ActivityIndicatorViewSize::Large: return "large";
case ActivityIndicatorViewSize::Small: return "small";
}
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,19 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
namespace facebook {
namespace react {
enum class ActivityIndicatorViewSize {
Large,
Small,
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,14 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <memory>
#include <gtest/gtest.h>
TEST(ActivityIndicatorViewTest, testSomething) {
// TODO
}

View File

@ -69,13 +69,6 @@ static const std::string componentNameByReactViewName(std::string viewName) {
return "View";
}
// Other temporary fallback until the native components are implemented.
if (
viewName == "ActivityIndicatorView"
) {
return "View";
}
return viewName;
}