diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.h b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.h new file mode 100644 index 000000000..470a3e7e0 --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.h @@ -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 + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * UIView class for root component. + */ +@interface RCTSwitchComponentView : RCTViewComponentView + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm new file mode 100644 index 000000000..ec54418bf --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -0,0 +1,88 @@ +/** + * 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 "RCTSwitchComponentView.h" + +#import +#import + +using namespace facebook::react; + +@implementation RCTSwitchComponentView { + UISwitch *_switchView; + BOOL _wasOn; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + _switchView = [[UISwitch alloc] initWithFrame:self.bounds]; + + [_switchView addTarget:self + action:@selector(onChange:) + forControlEvents:UIControlEventValueChanged]; + + auto &&defaultProps = SwitchProps(); + + _switchView.on = defaultProps.value; + + self.contentView = _switchView; + } + + return self; +} + +- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps +{ + if (!oldProps) { + oldProps = _props ?: std::make_shared(); + } + _props = props; + + [super updateProps:props oldProps:oldProps]; + + auto oldSwitchProps = *std::dynamic_pointer_cast(oldProps); + auto newSwitchProps = *std::dynamic_pointer_cast(props); + + // `value` + if (oldSwitchProps.value != newSwitchProps.value) { + _switchView.on = newSwitchProps.value; + _wasOn = newSwitchProps.value; + } + + // `disabled` + if (oldSwitchProps.disabled != newSwitchProps.disabled) { + _switchView.enabled = !newSwitchProps.disabled; + } + + // `tintColor` + if (oldSwitchProps.tintColor != newSwitchProps.tintColor) { + _switchView.tintColor = [UIColor colorWithCGColor:newSwitchProps.tintColor.get()]; + } + + // `onTintColor + if (oldSwitchProps.onTintColor != newSwitchProps.onTintColor) { + _switchView.onTintColor = [UIColor colorWithCGColor:newSwitchProps.onTintColor.get()]; + } + + // `thumbTintColor` + if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) { + _switchView.thumbTintColor = [UIColor colorWithCGColor:newSwitchProps.thumbTintColor.get()]; + } +} + +- (void)onChange:(UISwitch *)sender +{ + if (_wasOn == sender.on) { + return; + } + _wasOn = sender.on; + + std::dynamic_pointer_cast(_eventEmitter)->onChange(sender.on); +} + +@end diff --git a/ReactCommon/fabric/components/switch/BUCK b/ReactCommon/fabric/components/switch/BUCK new file mode 100644 index 000000000..8a4a27ff3 --- /dev/null +++ b/ReactCommon/fabric/components/switch/BUCK @@ -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 = "switch", + srcs = glob( + ["**/*.cpp"], + exclude = glob(["tests/**/*.cpp"]), + ), + headers = [], + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "fabric/components/switch", + ), + 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", + ":switch", + ], + ) diff --git a/ReactCommon/fabric/components/switch/SwitchComponentDescriptor.h b/ReactCommon/fabric/components/switch/SwitchComponentDescriptor.h new file mode 100644 index 000000000..1ea9e4582 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchComponentDescriptor.h @@ -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 +#include + +namespace facebook { +namespace react { + +using SwitchComponentDescriptor = ConcreteComponentDescriptor; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchEventEmitter.cpp b/ReactCommon/fabric/components/switch/SwitchEventEmitter.cpp new file mode 100644 index 000000000..680f1dbd5 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchEventEmitter.cpp @@ -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 "SwitchEventEmitter.h" + +namespace facebook { +namespace react { + +void SwitchEventEmitter::onChange(const bool &value) const { + dispatchEvent("change", folly::dynamic::object("value", value)); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchEventEmitter.h b/ReactCommon/fabric/components/switch/SwitchEventEmitter.h new file mode 100644 index 000000000..2f1cf3733 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchEventEmitter.h @@ -0,0 +1,25 @@ +/** + * 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 + +namespace facebook { +namespace react { + +class SwitchEventEmitter: + public ViewEventEmitter { + +public: + + using ViewEventEmitter::ViewEventEmitter; + + void onChange(const bool &value) const; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchProps.cpp b/ReactCommon/fabric/components/switch/SwitchProps.cpp new file mode 100644 index 000000000..9f80943c6 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchProps.cpp @@ -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 +#include + +namespace facebook { +namespace react { + +SwitchProps::SwitchProps(const SwitchProps &sourceProps, const RawProps &rawProps): + ViewProps(sourceProps, rawProps), + value(convertRawProp(rawProps, "value", sourceProps.value, value)), + disabled(convertRawProp(rawProps, "disabled", sourceProps.disabled, disabled)), + tintColor(convertRawProp(rawProps, "tintColor", sourceProps.tintColor, tintColor)), + onTintColor(convertRawProp(rawProps, "onTintColor", sourceProps.onTintColor, onTintColor)), + thumbTintColor(convertRawProp(rawProps, "thumbTintColor", sourceProps.thumbTintColor, thumbTintColor)) {} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchProps.h b/ReactCommon/fabric/components/switch/SwitchProps.h new file mode 100644 index 000000000..6ddac619b --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchProps.h @@ -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 +#include + +namespace facebook { +namespace react { + +// TODO (T28334063): Consider for codegen. +class SwitchProps final: + public ViewProps { + +public: + SwitchProps() = default; + SwitchProps(const SwitchProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + const bool value {false}; + const bool disabled {false}; + const SharedColor tintColor {}; + const SharedColor onTintColor {}; + const SharedColor thumbTintColor {}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchShadowNode.cpp b/ReactCommon/fabric/components/switch/SwitchShadowNode.cpp new file mode 100644 index 000000000..87896d0c6 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchShadowNode.cpp @@ -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 + +namespace facebook { +namespace react { + +ComponentName SwitchShadowNode::getComponentName() const { + return ComponentName("Switch"); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/SwitchShadowNode.h b/ReactCommon/fabric/components/switch/SwitchShadowNode.h new file mode 100644 index 000000000..b94256c74 --- /dev/null +++ b/ReactCommon/fabric/components/switch/SwitchShadowNode.h @@ -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 +#include +#include + +namespace facebook { +namespace react { + +/* + * `ShadowNode` for component. + */ +class SwitchShadowNode final: + public ConcreteViewShadowNode { + +public: + + using ConcreteViewShadowNode::ConcreteViewShadowNode; + + ComponentName getComponentName() const override; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/components/switch/tests/SwitchTest.cpp b/ReactCommon/fabric/components/switch/tests/SwitchTest.cpp new file mode 100644 index 000000000..a55a5783d --- /dev/null +++ b/ReactCommon/fabric/components/switch/tests/SwitchTest.cpp @@ -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 + +#include + +TEST(SwitchTest, testSomething) { + // TODO +}