From c79cb09c14c22283ac89cc7af29e0a3d2aedb0d9 Mon Sep 17 00:00:00 2001 From: Tadeu Zagallo Date: Mon, 9 Mar 2015 13:19:07 -0700 Subject: [PATCH] [ReactNative] Oss RCTSwitch --- ...cationExample.js => GeolocationExample.js} | 0 Examples/UIExplorer/SwitchExample.js | 141 ++++++++++ Examples/UIExplorer/UIExplorerList.js | 1 + .../Components/SwitchIOS/SwitchIOS.android.js | 41 +++ .../Components/SwitchIOS/SwitchIOS.ios.js | 117 ++++++++ .../RCTGeolocation.xcodeproj/project.pbxproj | 256 ++++++++++++++++++ Libraries/react-native/react-native.js | 1 + ReactKit/ReactKit.xcodeproj/project.pbxproj | 12 + ReactKit/Views/RCTSwitch.h | 10 + ReactKit/Views/RCTSwitch.m | 15 + ReactKit/Views/RCTSwitchManager.h | 7 + ReactKit/Views/RCTSwitchManager.m | 39 +++ 12 files changed, 640 insertions(+) rename Examples/UIExplorer/{GeoLocationExample.js => GeolocationExample.js} (100%) create mode 100644 Examples/UIExplorer/SwitchExample.js create mode 100644 Libraries/Components/SwitchIOS/SwitchIOS.android.js create mode 100644 Libraries/Components/SwitchIOS/SwitchIOS.ios.js create mode 100644 Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj create mode 100644 ReactKit/Views/RCTSwitch.h create mode 100644 ReactKit/Views/RCTSwitch.m create mode 100644 ReactKit/Views/RCTSwitchManager.h create mode 100644 ReactKit/Views/RCTSwitchManager.m diff --git a/Examples/UIExplorer/GeoLocationExample.js b/Examples/UIExplorer/GeolocationExample.js similarity index 100% rename from Examples/UIExplorer/GeoLocationExample.js rename to Examples/UIExplorer/GeolocationExample.js diff --git a/Examples/UIExplorer/SwitchExample.js b/Examples/UIExplorer/SwitchExample.js new file mode 100644 index 000000000..9aa63833f --- /dev/null +++ b/Examples/UIExplorer/SwitchExample.js @@ -0,0 +1,141 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @providesModule SwitchExample + */ +'use strict'; + +var React = require('react-native'); +var { + SwitchIOS, + Text, + View +} = React; + +var BasicSwitchExample = React.createClass({ + getInitialState() { + return { + trueSwitchIsOn: true, + falseSwitchIsOn: false, + }; + }, + render() { + return ( + + this.setState({falseSwitchIsOn: value})} + style={{marginBottom: 10}} + value={this.state.falseSwitchIsOn} /> + this.setState({trueSwitchIsOn: value})} + value={this.state.trueSwitchIsOn} /> + + ); + } +}); + +var DisabledSwitchExample = React.createClass({ + render() { + return ( + + + + + ); + }, +}); + +var ColorSwitchExample = React.createClass({ + getInitialState() { + return { + colorTrueSwitchIsOn: true, + colorFalseSwitchIsOn: false, + }; + }, + render() { + return ( + + this.setState({colorFalseSwitchIsOn: value})} + onTintColor="#00ff00" + style={{marginBottom: 10}} + thumbTintColor="#0000ff" + tintColor="#ff0000" + value={this.state.colorFalseSwitchIsOn} /> + this.setState({colorTrueSwitchIsOn: value})} + onTintColor="#00ff00" + thumbTintColor="#0000ff" + tintColor="#ff0000" + value={this.state.colorTrueSwitchIsOn} /> + + ); + }, +}); + +var EventSwitchExample = React.createClass({ + getInitialState() { + return { + eventSwitchIsOn: false, + eventSwitchRegressionIsOn: true, + }; + }, + render() { + return ( + + + this.setState({eventSwitchIsOn: value})} + style={{marginBottom: 10}} + value={this.state.eventSwitchIsOn} /> + this.setState({eventSwitchIsOn: value})} + style={{marginBottom: 10}} + value={this.state.eventSwitchIsOn} /> + {this.state.eventSwitchIsOn ? "On" : "Off"} + + + this.setState({eventSwitchRegressionIsOn: value})} + style={{marginBottom: 10}} + value={this.state.eventSwitchRegressionIsOn} /> + this.setState({eventSwitchRegressionIsOn: value})} + style={{marginBottom: 10}} + value={this.state.eventSwitchRegressionIsOn} /> + {this.state.eventSwitchRegressionIsOn ? "On" : "Off"} + + + ); + } +}); + +exports.title = ''; +exports.description = 'Native boolean input'; +exports.examples = [ + { + title: 'Switches can be set to true or false', + render() { return ; } + }, + { + title: 'Switches can be disabled', + render() { return ; } + }, + { + title: 'Custom colors can be provided', + render() { return ; } + }, + { + title: 'Change events can be detected', + render() { return ; } + }, + { + title: 'Switches are controlled components', + render() { return ; } + } +]; diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js index dd658b6ad..277517983 100644 --- a/Examples/UIExplorer/UIExplorerList.js +++ b/Examples/UIExplorer/UIExplorerList.js @@ -34,6 +34,7 @@ var EXAMPLES = [ require('./DatePickerExample'), require('./GeolocationExample'), require('./TabBarExample'), + require('./SwitchExample'), ]; var UIExplorerList = React.createClass({ diff --git a/Libraries/Components/SwitchIOS/SwitchIOS.android.js b/Libraries/Components/SwitchIOS/SwitchIOS.android.js new file mode 100644 index 000000000..72c24fa28 --- /dev/null +++ b/Libraries/Components/SwitchIOS/SwitchIOS.android.js @@ -0,0 +1,41 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @providesModule SwitchIOS + */ + +'use strict'; + +var React = require('React'); +var StyleSheet = require('StyleSheet'); +var Text = require('Text'); +var View = require('View'); + +var DummySwitchIOS = React.createClass({ + render: function() { + return ( + + SwitchIOS is not supported on this platform! + + ); + }, +}); + +var styles = StyleSheet.create({ + dummySwitchIOS: { + width: 120, + height: 50, + backgroundColor: '#ffbcbc', + borderWidth: 1, + borderColor: 'red', + alignItems: 'center', + justifyContent: 'center', + }, + text: { + color: '#333333', + margin: 5, + fontSize: 10, + } +}); + +module.exports = DummySwitchIOS; diff --git a/Libraries/Components/SwitchIOS/SwitchIOS.ios.js b/Libraries/Components/SwitchIOS/SwitchIOS.ios.js new file mode 100644 index 000000000..391b4da3a --- /dev/null +++ b/Libraries/Components/SwitchIOS/SwitchIOS.ios.js @@ -0,0 +1,117 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @providesModule SwitchIOS + * + * This is a controlled component version of RKSwitch. + */ +'use strict'; + +var NativeMethodsMixin = require('NativeMethodsMixin'); +var PropTypes = require('ReactPropTypes'); +var React = require('React'); +var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); +var StyleSheet = require('StyleSheet'); + +var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass'); +var merge = require('merge'); + +var SWITCH = 'switch'; + +/** + * Use `SwitchIOS` to render a boolean input on iOS. This is + * a controlled component, so you must hook in to the `onValueChange` callback + * and update the `value` prop in order for the component to update, otherwise + * the user's change will be reverted immediately to reflect `props.value` as the + * source of truth. + */ +var SwitchIOS = React.createClass({ + mixins: [NativeMethodsMixin], + + propTypes: { + /** + * The value of the switch, if true the switch will be turned on. + * Default value is false. + */ + value: PropTypes.bool, + + /** + * If true the user won't be able to toggle the switch. + * Default value is false. + */ + disabled: PropTypes.bool, + + /** + * Callback that is called when the user toggles the switch. + */ + onValueChange: PropTypes.func, + + /** + * Background color when the switch is turned on. + */ + onTintColor: PropTypes.string, + + /** + * Background color for the switch round button. + */ + thumbTintColor: PropTypes.string, + + /** + * Background color when the switch is turned off. + */ + tintColor: PropTypes.string, + }, + + getDefaultProps: function() { + return { + value: false, + disabled: false, + }; + }, + + _onChange: function(event) { + this.props.onChange && this.props.onChange(event); + this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value); + + // The underlying switch might have changed, but we're controlled, + // and so want to ensure it represents our value. + this.refs[SWITCH].setNativeProps({on: this.props.value}); + }, + + render: function() { + return ( + + ); + } +}); + +var styles = StyleSheet.create({ + rkSwitch: { + height: 31, + width: 51, + }, +}); + +var rkSwitchAttributes = merge(ReactIOSViewAttributes.UIView, { + onTintColor: true, + tintColor: true, + thumbTintColor: true, + on: true, + enabled: true, +}); + +var RKSwitch = createReactIOSNativeComponentClass({ + validAttributes: rkSwitchAttributes, + uiViewClassName: 'RCTSwitch', +}); + +module.exports = SwitchIOS; diff --git a/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj b/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj new file mode 100644 index 000000000..94f9c3f91 --- /dev/null +++ b/Libraries/GeoLocation/RCTGeolocation.xcodeproj/project.pbxproj @@ -0,0 +1,256 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 134814061AA4E45400B7C361 /* RCTLocationObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 134814051AA4E45400B7C361 /* RCTLocationObserver.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 58B511D91A9E6C8500147676 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 134814041AA4E45400B7C361 /* RCTLocationObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTLocationObserver.h; sourceTree = ""; }; + 134814051AA4E45400B7C361 /* RCTLocationObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLocationObserver.m; sourceTree = ""; }; + 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTGeolocation.a; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 58B511D81A9E6C8500147676 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 134814211AA4EA7D00B7C361 /* Products */ = { + isa = PBXGroup; + children = ( + 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 58B511D21A9E6C8500147676 = { + isa = PBXGroup; + children = ( + 134814041AA4E45400B7C361 /* RCTLocationObserver.h */, + 134814051AA4E45400B7C361 /* RCTLocationObserver.m */, + 134814211AA4EA7D00B7C361 /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 58B511DA1A9E6C8500147676 /* RCTGeolocation */ = { + isa = PBXNativeTarget; + buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTGeolocation" */; + buildPhases = ( + 58B511D71A9E6C8500147676 /* Sources */, + 58B511D81A9E6C8500147676 /* Frameworks */, + 58B511D91A9E6C8500147676 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RCTGeolocation; + productName = RCTDataManager; + productReference = 134814201AA4EA6300B7C361 /* libRCTGeolocation.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 58B511D31A9E6C8500147676 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 58B511DA1A9E6C8500147676 = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTGeolocation" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 58B511D21A9E6C8500147676; + productRefGroup = 58B511D21A9E6C8500147676; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 58B511DA1A9E6C8500147676 /* RCTGeolocation */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 58B511D71A9E6C8500147676 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 134814061AA4E45400B7C361 /* RCTLocationObserver.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 58B511ED1A9E6C8500147676 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 58B511EE1A9E6C8500147676 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 58B511F01A9E6C8500147676 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = RCTGeolocation; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 58B511F11A9E6C8500147676 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = RCTGeolocation; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTGeolocation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511ED1A9E6C8500147676 /* Debug */, + 58B511EE1A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTGeolocation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58B511F01A9E6C8500147676 /* Debug */, + 58B511F11A9E6C8500147676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 58B511D31A9E6C8500147676 /* Project object */; +} diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js index 944b9a53b..5aafb28ce 100644 --- a/Libraries/react-native/react-native.js +++ b/Libraries/react-native/react-native.js @@ -20,6 +20,7 @@ var ReactNative = { ActivityIndicatorIOS: require('ActivityIndicatorIOS'), StatusBarIOS: require('StatusBarIOS'), StyleSheet: require('StyleSheet'), + SwitchIOS: require('SwitchIOS'), Text: require('Text'), TextInput: require('TextInput'), TimerMixin: require('TimerMixin'), diff --git a/ReactKit/ReactKit.xcodeproj/project.pbxproj b/ReactKit/ReactKit.xcodeproj/project.pbxproj index 63dff04fb..dd9a452a0 100644 --- a/ReactKit/ReactKit.xcodeproj/project.pbxproj +++ b/ReactKit/ReactKit.xcodeproj/project.pbxproj @@ -35,6 +35,8 @@ 13E067571A70F44B002CDEE1 /* RCTView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067501A70F44B002CDEE1 /* RCTView.m */; }; 13E067591A70F44B002CDEE1 /* UIView+ReactKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+ReactKit.m */; }; 58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */; }; + 14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; }; + 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; }; 830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; }; 830BA4551A8E3BDA00D53203 /* RCTCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 830BA4541A8E3BDA00D53203 /* RCTCache.m */; }; 832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; }; @@ -125,6 +127,10 @@ 13EFFCCF1A98E6FE002607DC /* RCTJSMethodRegistrar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSMethodRegistrar.h; sourceTree = ""; }; 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDatePickerManager.m; sourceTree = ""; }; 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDatePickerManager.h; sourceTree = ""; }; + 14F362071AABD06A001CE568 /* RCTSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitch.h; sourceTree = ""; }; + 14F362081AABD06A001CE568 /* RCTSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitch.m; sourceTree = ""; }; + 14F362091AABD06A001CE568 /* RCTSwitchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSwitchManager.h; sourceTree = ""; }; + 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitchManager.m; sourceTree = ""; }; 830213F31A654E0800B993E6 /* RCTBridgeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeModule.h; sourceTree = ""; }; 830A229C1A66C68A008503DA /* RCTRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootView.h; sourceTree = ""; }; 830A229D1A66C68A008503DA /* RCTRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootView.m; sourceTree = ""; }; @@ -204,6 +210,10 @@ 13B07FF31A6947C200A75B9A /* Views */ = { isa = PBXGroup; children = ( + 14F362071AABD06A001CE568 /* RCTSwitch.h */, + 14F362081AABD06A001CE568 /* RCTSwitch.m */, + 14F362091AABD06A001CE568 /* RCTSwitchManager.h */, + 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */, 13442BF21AA90E0B0037E5B0 /* RCTAnimationType.h */, 58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */, 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */, @@ -398,6 +408,8 @@ 83CBBA5A1A601E9000E9B192 /* RCTRedBox.m in Sources */, 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */, 832348161A77A5AA00B55238 /* Layout.c in Sources */, + 14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */, + 14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */, 13B080201A69489C00A75B9A /* RCTUIActivityIndicatorViewManager.m in Sources */, 13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */, 58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */, diff --git a/ReactKit/Views/RCTSwitch.h b/ReactKit/Views/RCTSwitch.h new file mode 100644 index 000000000..7866eb866 --- /dev/null +++ b/ReactKit/Views/RCTSwitch.h @@ -0,0 +1,10 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + + +#import + +@interface RCTSwitch : UISwitch + +@property (nonatomic, assign) BOOL wasOn; + +@end diff --git a/ReactKit/Views/RCTSwitch.m b/ReactKit/Views/RCTSwitch.m new file mode 100644 index 000000000..70233fede --- /dev/null +++ b/ReactKit/Views/RCTSwitch.m @@ -0,0 +1,15 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTSwitch.h" + +#import "RCTEventDispatcher.h" +#import "UIView+ReactKit.h" + +@implementation RCTSwitch + +- (void)setOn:(BOOL)on animated:(BOOL)animated { + _wasOn = on; + [super setOn:on animated:animated]; +} + +@end diff --git a/ReactKit/Views/RCTSwitchManager.h b/ReactKit/Views/RCTSwitchManager.h new file mode 100644 index 000000000..f6833d106 --- /dev/null +++ b/ReactKit/Views/RCTSwitchManager.h @@ -0,0 +1,7 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTViewManager.h" + +@interface RCTSwitchManager : RCTViewManager + +@end diff --git a/ReactKit/Views/RCTSwitchManager.m b/ReactKit/Views/RCTSwitchManager.m new file mode 100644 index 000000000..61eab8199 --- /dev/null +++ b/ReactKit/Views/RCTSwitchManager.m @@ -0,0 +1,39 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTSwitchManager.h" + +#import "RCTBridge.h" +#import "RCTEventDispatcher.h" +#import "RCTSwitch.h" +#import "UIView+ReactKit.h" + +@implementation RCTSwitchManager + +- (UIView *)view +{ + RCTSwitch *switcher = [[RCTSwitch alloc] init]; + [switcher addTarget:self + action:@selector(onChange:) + forControlEvents:UIControlEventValueChanged]; + return switcher; +} + +- (void)onChange:(RCTSwitch *)sender +{ + if (sender.wasOn != sender.on) { + [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:@{ + @"target": sender.reactTag, + @"value": @(sender.on) + }]; + + sender.wasOn = sender.on; + } +} + +RCT_EXPORT_VIEW_PROPERTY(onTintColor); +RCT_EXPORT_VIEW_PROPERTY(tintColor); +RCT_EXPORT_VIEW_PROPERTY(thumbTintColor); +RCT_EXPORT_VIEW_PROPERTY(on); +RCT_EXPORT_VIEW_PROPERTY(enabled); + +@end