Integrate Picker into Fabric on Android

Summary:
In this diff we integrate the Picker component on Android in Fabric. Since both AndroidDropdownPickerNativeComponent and AndroidDialogPickerNativeComponent use `style?: ?TextStyleProp`, which is not supported by the JS codegen, I had to handwrite the C++ files and check them in.

The component is not fully functional yet because `setNativeProps` is not supported in Fabric. I will fix this in the next diff.

Changelog:
[Android] [Added] - Integrate Picker into Fabric on Android

Reviewed By: mdvacca

Differential Revision: D17954435

fbshipit-source-id: 6b7b029ab0c84c27a48c7dddd66878c9dea324bf
This commit is contained in:
Oleksandr Melnykov 2019-11-11 09:09:49 -08:00 коммит произвёл Facebook Github Bot
Родитель 28a3b25c31
Коммит 9ff090e507
15 изменённых файлов: 539 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,96 @@
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load(
"//tools/build_defs/oss:rn_defs.bzl",
"ANDROID",
"APPLE",
"CXX",
"YOGA_CXX_TARGET",
"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 = "androidpicker",
srcs = glob(
["**/*.cpp"],
exclude = glob(["tests/**/*.cpp"]),
),
headers = glob(
["**/*.h"],
exclude = glob(["tests/**/*.h"]),
),
header_namespace = "",
exported_headers = subdir_glob(
[
("", "*.h"),
("androidpicker", "*.h"),
],
prefix = "react/components/androidpicker",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
cxx_tests = [":tests"],
fbandroid_deps = [
react_native_target("jni/react/jni:jni"),
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(),
force_static = True,
platforms = (ANDROID, APPLE, CXX),
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/graphics:graphics"),
react_native_xplat_target("fabric/components/view:view"),
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 = (
# `Apple` and `Android` flavors are disabled because the module depends on `textlayoutmanager` which requires real an Emulator/Simulator to run.
# At the same time, the code of tests does not rely on the simulator capabilities and it would be wasteful to add `fbandroid_use_instrumentation_test = True`.
# (Beware of this option though.)
# ANDROID,
# APPLE,
CXX
),
deps = [
"fbsource//xplat/folly:molly",
"fbsource//xplat/third-party/gmock:gtest",
":androidpicker",
],
)

Просмотреть файл

@ -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.
*/
#pragma once
#include "AndroidDialogPickerShadowNode.h"
#include <react/core/ConcreteComponentDescriptor.h>
namespace facebook {
namespace react {
using AndroidDialogPickerComponentDescriptor =
ConcreteComponentDescriptor<AndroidDialogPickerShadowNode>;
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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.
*/
#include "AndroidDialogPickerEventEmitter.h"
namespace facebook {
namespace react {
void AndroidDialogPickerEventEmitter::onSelect(
AndroidDialogPickerOnSelectStruct event) const {
dispatchEvent("select", [event = std::move(event)](jsi::Runtime &runtime) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "position", event.position);
return payload;
});
}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,27 @@
/*
* 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/view/ViewEventEmitter.h>
namespace facebook {
namespace react {
struct AndroidDialogPickerOnSelectStruct {
int position;
};
class AndroidDialogPickerEventEmitter : public ViewEventEmitter {
public:
using ViewEventEmitter::ViewEventEmitter;
void onSelect(AndroidDialogPickerOnSelectStruct value) const;
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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 "AndroidDialogPickerProps.h"
#include <react/components/image/conversions.h>
#include <react/core/propsConversions.h>
namespace facebook {
namespace react {
AndroidDialogPickerProps::AndroidDialogPickerProps(
const AndroidDialogPickerProps &sourceProps,
const RawProps &rawProps)
: ViewProps(sourceProps, rawProps),
color(convertRawProp(rawProps, "color", sourceProps.color, {})),
enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})),
items(convertRawProp(rawProps, "items", sourceProps.items, {})),
prompt(convertRawProp(rawProps, "prompt", sourceProps.prompt, {""})),
selected(
convertRawProp(rawProps, "selected", sourceProps.selected, {0})) {}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,77 @@
/*
* 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/view/ViewProps.h>
#include <react/core/propsConversions.h>
#include <react/graphics/Color.h>
#include <react/imagemanager/primitives.h>
#include <cinttypes>
#include <vector>
namespace facebook {
namespace react {
struct AndroidDialogPickerItemsStruct {
std::string label;
int color;
};
static inline void fromRawValue(
const RawValue &value,
AndroidDialogPickerItemsStruct &result) {
auto map = (better::map<std::string, RawValue>)value;
auto label = map.find("label");
if (label != map.end()) {
fromRawValue(label->second, result.label);
}
auto color = map.find("color");
// C++ props are not used on Android at the moment, so we can leave
// result.color uninitialized if the JS prop has a null value. TODO: revisit
// this once we start using C++ props on Android.
if (color != map.end() && color->second.hasValue()) {
fromRawValue(color->second, result.color);
}
}
static inline std::string toString(
const AndroidDialogPickerItemsStruct &value) {
return "[Object AndroidDialogPickerItemsStruct]";
}
static inline void fromRawValue(
const RawValue &value,
std::vector<AndroidDialogPickerItemsStruct> &result) {
auto items = (std::vector<RawValue>)value;
for (const auto &item : items) {
AndroidDialogPickerItemsStruct newItem;
fromRawValue(item, newItem);
result.emplace_back(newItem);
}
}
class AndroidDialogPickerProps final : public ViewProps {
public:
AndroidDialogPickerProps() = default;
AndroidDialogPickerProps(
const AndroidDialogPickerProps &sourceProps,
const RawProps &rawProps);
#pragma mark - Props
const SharedColor color{};
const bool enabled{true};
const std::vector<AndroidDialogPickerItemsStruct> items{};
const std::string prompt{""};
const int selected{0};
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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 "AndroidDialogPickerShadowNode.h"
namespace facebook {
namespace react {
extern const char AndroidDialogPickerComponentName[] = "AndroidDialogPicker";
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,29 @@
/*
* 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 "AndroidDialogPickerEventEmitter.h"
#include "AndroidDialogPickerProps.h"
#include <react/components/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
extern const char AndroidDialogPickerComponentName[];
/*
* `ShadowNode` for <AndroidDialogPicker> component.
*/
using AndroidDialogPickerShadowNode = ConcreteViewShadowNode<
AndroidDialogPickerComponentName,
AndroidDialogPickerProps,
AndroidDialogPickerEventEmitter>;
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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.
*/
#pragma once
#include "AndroidDropdownPickerShadowNode.h"
#include <react/core/ConcreteComponentDescriptor.h>
namespace facebook {
namespace react {
using AndroidDropdownPickerComponentDescriptor =
ConcreteComponentDescriptor<AndroidDropdownPickerShadowNode>;
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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.
*/
#include "AndroidDropdownPickerEventEmitter.h"
namespace facebook {
namespace react {
void AndroidDropdownPickerEventEmitter::onSelect(
AndroidDropdownPickerOnSelectStruct event) const {
dispatchEvent("select", [event = std::move(event)](jsi::Runtime &runtime) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "position", event.position);
return payload;
});
}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,27 @@
/*
* 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/view/ViewEventEmitter.h>
namespace facebook {
namespace react {
struct AndroidDropdownPickerOnSelectStruct {
int position;
};
class AndroidDropdownPickerEventEmitter : public ViewEventEmitter {
public:
using ViewEventEmitter::ViewEventEmitter;
void onSelect(AndroidDropdownPickerOnSelectStruct value) const;
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -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 "AndroidDropdownPickerProps.h"
#include <react/components/image/conversions.h>
#include <react/core/propsConversions.h>
namespace facebook {
namespace react {
AndroidDropdownPickerProps::AndroidDropdownPickerProps(
const AndroidDropdownPickerProps &sourceProps,
const RawProps &rawProps)
: ViewProps(sourceProps, rawProps),
color(convertRawProp(rawProps, "color", sourceProps.color, {})),
enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})),
items(convertRawProp(rawProps, "items", sourceProps.items, {})),
prompt(convertRawProp(rawProps, "prompt", sourceProps.prompt, {""})),
selected(
convertRawProp(rawProps, "selected", sourceProps.selected, {0})) {}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,77 @@
/*
* 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/view/ViewProps.h>
#include <react/core/propsConversions.h>
#include <react/graphics/Color.h>
#include <react/imagemanager/primitives.h>
#include <cinttypes>
#include <vector>
namespace facebook {
namespace react {
struct AndroidDropdownPickerItemsStruct {
std::string label;
int color;
};
static inline void fromRawValue(
const RawValue &value,
AndroidDropdownPickerItemsStruct &result) {
auto map = (better::map<std::string, RawValue>)value;
auto label = map.find("label");
if (label != map.end()) {
fromRawValue(label->second, result.label);
}
auto color = map.find("color");
// C++ props are not used on Android at the moment, so we can leave
// result.color uninitialized if the JS prop has a null value. TODO: revisit
// this once we start using C++ props on Android.
if (color != map.end() && color->second.hasValue()) {
fromRawValue(color->second, result.color);
}
}
static inline std::string toString(
const AndroidDropdownPickerItemsStruct &value) {
return "[Object AndroidDropdownPickerItemsStruct]";
}
static inline void fromRawValue(
const RawValue &value,
std::vector<AndroidDropdownPickerItemsStruct> &result) {
auto items = (std::vector<RawValue>)value;
for (const auto &item : items) {
AndroidDropdownPickerItemsStruct newItem;
fromRawValue(item, newItem);
result.emplace_back(newItem);
}
}
class AndroidDropdownPickerProps final : public ViewProps {
public:
AndroidDropdownPickerProps() = default;
AndroidDropdownPickerProps(
const AndroidDropdownPickerProps &sourceProps,
const RawProps &rawProps);
#pragma mark - Props
const SharedColor color{};
const bool enabled{true};
const std::vector<AndroidDropdownPickerItemsStruct> items{};
const std::string prompt{""};
const int selected{0};
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,17 @@
/*
* 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 "AndroidDropdownPickerShadowNode.h"
namespace facebook {
namespace react {
extern const char AndroidDropdownPickerComponentName[] =
"AndroidDropdownPicker";
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,29 @@
/*
* 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 "AndroidDropdownPickerEventEmitter.h"
#include "AndroidDropdownPickerProps.h"
#include <react/components/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
extern const char AndroidDropdownPickerComponentName[];
/*
* `ShadowNode` for <AndroidDropdownPicker> component.
*/
using AndroidDropdownPickerShadowNode = ConcreteViewShadowNode<
AndroidDropdownPickerComponentName,
AndroidDropdownPickerProps,
AndroidDropdownPickerEventEmitter>;
} // namespace react
} // namespace facebook