diff --git a/ReactCommon/fabric/components/picker/BUCK b/ReactCommon/fabric/components/picker/BUCK new file mode 100644 index 0000000000..f77c45194a --- /dev/null +++ b/ReactCommon/fabric/components/picker/BUCK @@ -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", + ], +) diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerComponentDescriptor.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerComponentDescriptor.h new file mode 100644 index 0000000000..c83b7ed3df --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerComponentDescriptor.h @@ -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 + +namespace facebook { +namespace react { + +using AndroidDialogPickerComponentDescriptor = + ConcreteComponentDescriptor; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.cpp new file mode 100644 index 0000000000..983a7f5dff --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.cpp @@ -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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.h new file mode 100644 index 0000000000..9ea91f192c --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerEventEmitter.h @@ -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 + +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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.cpp new file mode 100644 index 0000000000..8996776d93 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.cpp @@ -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 +#include + +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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.h new file mode 100644 index 0000000000..33aa151d87 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerProps.h @@ -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 +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +struct AndroidDialogPickerItemsStruct { + std::string label; + int color; +}; + +static inline void fromRawValue( + const RawValue &value, + AndroidDialogPickerItemsStruct &result) { + auto map = (better::map)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 &result) { + auto items = (std::vector)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 items{}; + const std::string prompt{""}; + const int selected{0}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.cpp new file mode 100644 index 0000000000..e101c71b02 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.cpp @@ -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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.h new file mode 100644 index 0000000000..d0483996dc --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDialogPickerShadowNode.h @@ -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 + +namespace facebook { +namespace react { + +extern const char AndroidDialogPickerComponentName[]; + +/* + * `ShadowNode` for component. + */ +using AndroidDialogPickerShadowNode = ConcreteViewShadowNode< + AndroidDialogPickerComponentName, + AndroidDialogPickerProps, + AndroidDialogPickerEventEmitter>; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerComponentDescriptor.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerComponentDescriptor.h new file mode 100644 index 0000000000..f3ec83aead --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerComponentDescriptor.h @@ -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 + +namespace facebook { +namespace react { + +using AndroidDropdownPickerComponentDescriptor = + ConcreteComponentDescriptor; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.cpp new file mode 100644 index 0000000000..df52918bac --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.cpp @@ -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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.h new file mode 100644 index 0000000000..01db35b119 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerEventEmitter.h @@ -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 + +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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.cpp new file mode 100644 index 0000000000..4aa8883e71 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.cpp @@ -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 +#include + +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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.h new file mode 100644 index 0000000000..94af9d84cf --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerProps.h @@ -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 +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +struct AndroidDropdownPickerItemsStruct { + std::string label; + int color; +}; + +static inline void fromRawValue( + const RawValue &value, + AndroidDropdownPickerItemsStruct &result) { + auto map = (better::map)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 &result) { + auto items = (std::vector)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 items{}; + const std::string prompt{""}; + const int selected{0}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.cpp b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.cpp new file mode 100644 index 0000000000..724a2fde03 --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.cpp @@ -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 diff --git a/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.h b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.h new file mode 100644 index 0000000000..bf1661414e --- /dev/null +++ b/ReactCommon/fabric/components/picker/androidpicker/AndroidDropdownPickerShadowNode.h @@ -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 + +namespace facebook { +namespace react { + +extern const char AndroidDropdownPickerComponentName[]; + +/* + * `ShadowNode` for component. + */ +using AndroidDropdownPickerShadowNode = ConcreteViewShadowNode< + AndroidDropdownPickerComponentName, + AndroidDropdownPickerProps, + AndroidDropdownPickerEventEmitter>; + +} // namespace react +} // namespace facebook