├── .babelrc ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .tern-project ├── .watchmanconfig ├── README.md ├── RNTodoMVC.png ├── android ├── app │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── reactnativeboilerplate │ │ │ └── MainActivity.java │ │ └── res │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── index.android.js ├── index.ios.js ├── installPlugins.js ├── ios ├── ReactNativeBoilerplate.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── ReactNativeBoilerplate.xcscheme ├── ReactNativeBoilerplate │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── main.m ├── ReactNativeBoilerplateTests │ ├── Info.plist │ └── ReactNativeBoilerplateTests.m └── main.jsbundle ├── jestSupport └── scriptPreprocess.js ├── js ├── App.js ├── actionCreators │ ├── NavigationActionCreators.js │ └── TodoActionCreators.js ├── components │ ├── TodoFilterBar.js │ ├── TodoList.js │ ├── TodoListItem.js │ └── TodoTextInput.js ├── constants │ ├── NavigationActionTypes.js │ ├── NavigationConstants.js │ ├── NavigatorKeys.js │ ├── TodoActionTypes.js │ └── TodoFilters.js ├── containers │ ├── AppContainer.js │ ├── Navigator.js │ └── Todos.js ├── middleware │ └── DispatchLogger.js ├── reducers │ ├── NavigationReducer.js │ ├── TodoReducer.js │ └── index.js ├── selectors │ ├── NavigationSelectors.js │ └── TodoSelectors.js ├── styles │ ├── Color.js │ └── index.js └── util │ ├── keyMirror.js │ ├── log.js │ ├── mergeById.js │ └── persistenceTransformer.js ├── package.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "retainLines": true, 3 | "compact": true, 4 | "comments": false, 5 | "whitelist": [ 6 | "es6.arrowFunctions", 7 | "es6.blockScoping", 8 | "es6.classes", 9 | "es6.constants", 10 | "es6.destructuring", 11 | "es6.parameters", 12 | "es6.properties.computed", 13 | "es6.properties.shorthand", 14 | "es6.spread", 15 | "es6.modules", 16 | "es6.templateLiterals", 17 | "es7.trailingFunctionCommas", 18 | "es7.objectRestSpread", 19 | "es7.classProperties", 20 | "flow", 21 | "react", 22 | "react.displayName", 23 | "regenerator" 24 | ], 25 | "sourceMaps": false 26 | } 27 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "react" 4 | ], 5 | "globals": { 6 | "Promise": false 7 | }, 8 | "rules": { 9 | "comma-dangle": [ 2, "never" ], 10 | "no-cond-assign": [ 2, "always" ], 11 | "no-console": 1, 12 | "no-constant-condition": 2, 13 | "no-control-regex": 2, 14 | "no-debugger": 2, 15 | "no-dupe-args": 2, 16 | "no-dupe-keys": 2, 17 | "no-duplicate-case": 2, 18 | "no-empty": 2, 19 | "no-empty-character-class": 2, 20 | "no-ex-assign": 2, 21 | "no-extra-boolean-cast": 2, 22 | "no-extra-parens": 0, 23 | "no-extra-semi": 2, 24 | "no-func-assign": 2, 25 | "no-inner-declarations": [ 0, "both" ], 26 | "no-invalid-regexp": 2, 27 | "no-irregular-whitespace": 2, 28 | "no-negated-in-lhs": 2, 29 | "no-obj-calls": 2, 30 | "no-regex-spaces": 2, 31 | "no-reserved-keys": 0, 32 | "no-sparse-arrays": 2, 33 | "no-unreachable": 2, 34 | "use-isnan": 2, 35 | "valid-jsdoc": 0, 36 | "valid-typeof": 2, 37 | "no-unexpected-multiline": 2, 38 | "accessor-pairs": [ 2, { "getWithoutSet": false, "setWithoutGet": true }], 39 | "block-scoped-var": 2, 40 | "complexity": [ 0, 11 ], 41 | "consistent-return": 2, 42 | "curly": [ 2, "multi-line" ], 43 | "default-case": 0, 44 | "dot-location": [ 2, "property" ], 45 | "dot-notation": [ 0, { "allowKeywords": true }], 46 | "eqeqeq": 0, 47 | "guard-for-in": 2, 48 | "no-alert": 2, 49 | "no-caller": 2, 50 | "no-div-regex": 2, 51 | "no-else-return": 0, 52 | "no-empty-label": 2, 53 | "no-eq-null": 0, 54 | "no-eval": 2, 55 | "no-extend-native": 2, 56 | "no-extra-bind": 2, 57 | "no-fallthrough": 2, 58 | "no-floating-decimal": 0, 59 | "no-implied-eval": 2, 60 | "no-iterator": 2, 61 | "no-labels": 2, 62 | "no-lone-blocks": 2, 63 | "no-loop-func": 2, 64 | "no-multi-spaces": 2, 65 | "no-multi-str": 2, 66 | "no-native-reassign": 2, 67 | "no-new": 1, 68 | "no-new-func": 2, 69 | "no-new-wrappers": 2, 70 | "no-octal": 2, 71 | "no-octal-escape": 2, 72 | "no-param-reassign": 0, 73 | "no-process-env": 0, 74 | "no-proto": 2, 75 | "no-redeclare": 2, 76 | "no-return-assign": [ 2, "always" ], 77 | "no-script-url": 2, 78 | "no-self-compare": 2, 79 | "no-sequences": 2, 80 | "no-throw-literal": 2, 81 | "no-unused-expressions": 0, 82 | "no-void": 2, 83 | "no-warning-comments": 1, 84 | "no-with": 2, 85 | "radix": 2, 86 | "vars-on-top": 0, 87 | "wrap-iife": [ 2, "inside" ], 88 | "yoda": [ 1, "never" ], 89 | "strict": [ 2, "global" ], 90 | "no-catch-shadow": 0, 91 | "no-delete-var": 2, 92 | "no-label-var": 2, 93 | "no-shadow": 2, 94 | "no-shadow-restricted-names": 2, 95 | "no-undef": 2, 96 | "no-undef-init": 2, 97 | "no-undefined": 0, 98 | "no-unused-vars": [ 2, { "vars": "all", "args": "none" }], 99 | "no-use-before-define": [1, "nofunc"], 100 | "handle-callback-err": [ 2, "err" ], 101 | "no-mixed-requires": [ 0, true ], 102 | "no-new-require": 2, 103 | "no-path-concat": 2, 104 | "no-process-exit": 2, 105 | "no-restricted-modules": 0, 106 | "no-sync": 0, 107 | "array-bracket-spacing": [ 0, "always"], 108 | "brace-style": [ 0, "stroustrup", { "allowSingleLine": false }], 109 | "camelcase": [2, {"properties":"never"}], 110 | "comma-spacing": [ 2, { "before": false, "after": true }], 111 | "comma-style": [ 0, "last" ], 112 | "computed-property-spacing": [2, "never"], 113 | "consistent-this": [ 2, "that" ], 114 | "eol-last": 0, 115 | "func-names": 0, 116 | "func-style": [ 0, "expression" ], 117 | "key-spacing": [ 2, { "beforeColon": false, "afterColon": true }], 118 | "linebreak-style": [ 2, "unix" ], 119 | "lines-around-comment": [ 2, { 120 | "beforeBlockComment": false, 121 | "afterBlockComment": false, 122 | "beforeLineComment": false, 123 | "afterLineComment": false, 124 | "allowBlockStart": true, 125 | "allowBlockEnd": true 126 | }], 127 | "max-nested-callbacks": [ 0, 3 ], 128 | "new-cap": [ 2, { "newIsCap": true, "capIsNew": false }], 129 | "new-parens": 2, 130 | "newline-after-var": [ 0, "always" ], 131 | "no-array-constructor": 2, 132 | "no-continue": 0, 133 | "no-inline-comments": 0, 134 | "no-lonely-if": 1, 135 | "no-mixed-spaces-and-tabs": [ 2 ], 136 | "no-multiple-empty-lines": [ 2, { "max": 2 }], 137 | "no-nested-ternary": 0, 138 | "no-new-object": 2, 139 | "no-spaced-func": 2, 140 | "no-ternary": 0, 141 | "no-trailing-spaces": [ 2, { "skipBlankLines": false }], 142 | "no-underscore-dangle": 0, 143 | "no-unneeded-ternary": 2, 144 | "object-curly-spacing": [1, "always", { 145 | "objectsInObjects": true, 146 | "arraysInObjects": true 147 | }], 148 | "one-var": 0, 149 | "operator-assignment": [ 2, "always" ], 150 | "operator-linebreak": [ 0, "before" ], 151 | "quotes": [ 1, "single" ], 152 | "semi": [ 2, "always" ], 153 | "semi-spacing": [ 2, { "before": false, "after": true }], 154 | "sort-vars": [ 0, { "ignoreCase": true }], 155 | "space-after-keywords": [ 2, "always" ], 156 | "space-before-blocks": [ 2, "always" ], 157 | "space-before-function-paren": [ 2, { "anonymous": "never", "named": "never" }], 158 | "space-in-parens": [ 2, "never" ], 159 | "space-infix-ops": [ 2, { "int32Hint": false }], 160 | "space-return-throw-case": 2, 161 | "space-unary-ops": [ 2, { "words": true, "nonwords": false }], 162 | "spaced-comment": 0, 163 | "wrap-regex": 0, 164 | "no-const-assign": 2, 165 | "constructor-super": 2, 166 | "generator-star-spacing": [ 2, "both" ], 167 | "no-this-before-super": 2, 168 | "no-var": 2, 169 | "object-shorthand": [ 2, "methods" ], 170 | "prefer-const": 0, 171 | "prefer-spread": 2, 172 | "max-depth": [ 0, 4 ], 173 | "max-len": [ 0, 120, 4 ], 174 | "max-params": [ 0, 11 ], 175 | "max-statements": [ 0, 100 ], 176 | "no-bitwise": 0, 177 | "no-plusplus": 0, 178 | "react/jsx-boolean-value": 0, 179 | "react/jsx-no-duplicate-props": 1, 180 | "react/jsx-no-undef": 1, 181 | "react/jsx-quotes": [1, "double"], 182 | "react/jsx-uses-react": 1, 183 | "react/jsx-uses-vars": 1, 184 | "react/no-unknown-property": 2, 185 | "react/react-in-jsx-scope": 1, 186 | "react/self-closing-comp": 1, 187 | "react/wrap-multilines": 1 188 | }, 189 | "env": { 190 | "es6": true, 191 | "browser": true, 192 | "node": true 193 | }, 194 | "extends": "eslint:recommended", 195 | "ecmaFeatures": { 196 | "arrowFunctions": true, 197 | "binaryLiterals": true, 198 | "blockBindings": true, 199 | "classes": true, 200 | "defaultParams": true, 201 | "destructuring": true, 202 | "forOf": true, 203 | "generators": true, 204 | "globalReturn": false, 205 | "modules": true, 206 | "objectLiteralComputedProperties": true, 207 | "objectLiteralDuplicateProperties": false, 208 | "objectLiteralShorthandMethods": true, 209 | "objectLiteralShorthandProperties": true, 210 | "octalLiterals": true, 211 | "regexUFlag": true, 212 | "regexYFlag": true, 213 | "restParams": true, 214 | "spread": true, 215 | "superInFunctions": true, 216 | "templateStrings": true, 217 | "unicodeCodePointEscapes": true, 218 | "jsx": true, 219 | "experimentalObjectRestSpread": true 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | # We fork some components by platform. 4 | .*/*.web.js 5 | .*/*.android.js 6 | 7 | # Some modules have their own node_modules with overlap 8 | .*/node_modules/node-haste/.* 9 | 10 | # Ignore react-tools where there are overlaps, but don't ignore anything that 11 | # react-native relies on 12 | .*/node_modules/react-tools/src/React.js 13 | .*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js 14 | .*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js 15 | .*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js 16 | 17 | # Ignore commoner tests 18 | .*/node_modules/commoner/test/.* 19 | 20 | # See https://github.com/facebook/flow/issues/442 21 | .*/react-tools/node_modules/commoner/lib/reader.js 22 | 23 | # Ignore jest 24 | .*/node_modules/jest-cli/.* 25 | 26 | # Ignore Website 27 | .*/website/.* 28 | 29 | [include] 30 | 31 | [libs] 32 | node_modules/react-native/Libraries/react-native/react-native-interface.js 33 | 34 | [options] 35 | module.system=haste 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 40 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.png$' -> 'RelativeImageStub' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FixMe 45 | 46 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-7]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-7]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+ 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 49 | 50 | [version] 51 | 0.17.0 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | .idea 28 | .gradle 29 | local.properties 30 | 31 | # node.js 32 | # 33 | node_modules/ 34 | npm-debug.log 35 | -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaVersion": 6, 3 | "libs": [], 4 | "loadEagerly": [] 5 | } 6 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-boilerplate 2 | 3 | A "boilerplate" React Native application with an example "Todo" implementation and with the following features: 4 | 5 | - Full ES6 support 6 | - `redux` 7 | - `immutable` data persisted to `AsyncStorage` on state change and rehydrated on app load with `redux-persist` 8 | - A custom `Navigator` component controlled via actions 9 | - Logging with `minilog` 10 | - ESLint 11 | 12 | ![App Screenshot](https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/master/RNTodoMVC.png) 13 | 14 | ## Currently iOS only! 15 | 16 | ## Structure 17 | 18 | - **android** 19 | - React Native created Android project for the app 20 | - **ios** 21 | - React Native created XCode project for the iOS app 22 | - **js** 23 | - **actionCreators** 24 | - Functions used throughout the app to create and dispatch `redux` actions 25 | - **components** 26 | - Reusable React components 27 | - **constants** 28 | - The app's constants 29 | - **containers** 30 | - High level components that connect to the `redux` store and pass props down to components, these typically map to the "Screens" of an app like "Settings" or "Dashboard", and potentially sub-views that have their own complex component hierarchy 31 | - **middleware** 32 | - Middleware receive dispatched actions before reducers, can interrupt the flow or allow it to continue, and can have side effects like logging the action or even dispatching other actions 33 | - **reducers** 34 | - Functions that respond to dispatched actions and return a modified version of the state 35 | - **selectors** 36 | - Functions used by containers and components to request a particular piece of the state tree 37 | - **styles** 38 | - Styling helpers 39 | - **util** 40 | - **persistenceTransformer.js** 41 | - this utility handles transformation as the state tree is persisted and rehydrated from local storage using `redux-persist` 42 | - Otherwise, just common application utilities 43 | - **App.js** 44 | - Common `redux` app entry point and setup 45 | - Initializes `redux` store, middleware, reducers, and persistence 46 | - **.babelrc** 47 | - the config for babel, enables ES6+ features 48 | - **.eslintrc** 49 | - ESLint configuration 50 | - **.flowconfig** 51 | - React Native default FlowType configuration, no flow type annotations are currently in use 52 | - **.gitignore** 53 | - React Native default .gitignore 54 | - **.tern-project** 55 | - Tern configuration for Atom autocomplete 56 | - **.watchmanconfig** 57 | - React Native default .watchmanconfig 58 | - **index.android.js** 59 | - Entry point for Android app (not currently supported) 60 | - **index.ios.js** 61 | - Entry point for iOS app 62 | - **package.json** 63 | - Project's NPM dependencies, configuration, and scripts 64 | - **README.md** 65 | - This file 66 | - **stateMock.js** 67 | - A mock of the `redux` app's state tree to assist in visualizing it as a whole 68 | -------------------------------------------------------------------------------- /RNTodoMVC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/RNTodoMVC.png -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.reactnativeboilerplate" 9 | minSdkVersion 16 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | ndk { 14 | abiFilters "armeabi-v7a", "x86" 15 | } 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false // Set this to true to enable Proguard 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | compile 'com.android.support:appcompat-v7:23.0.1' 28 | compile 'com.facebook.react:react-native:0.13.+' 29 | } 30 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | 30 | # Do not strip any method/class that is annotated with @DoNotStrip 31 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 32 | -keepclassmembers class * { 33 | @com.facebook.proguard.annotations.DoNotStrip *; 34 | } 35 | 36 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 37 | void set*(***); 38 | *** get*(); 39 | } 40 | 41 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 42 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 43 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 44 | -keepclassmembers class * { @com.facebook.react.uimanager.ReactProp ; } 45 | -keepclassmembers class * { @com.facebook.react.uimanager.ReactPropGroup ; } 46 | 47 | # okhttp 48 | 49 | -keepattributes Signature 50 | -keepattributes *Annotation* 51 | -keep class com.squareup.okhttp.** { *; } 52 | -keep interface com.squareup.okhttp.** { *; } 53 | -dontwarn com.squareup.okhttp.** 54 | 55 | # okio 56 | 57 | -keep class sun.misc.Unsafe { *; } 58 | -dontwarn java.nio.file.* 59 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 60 | -dontwarn okio.** 61 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/reactnativeboilerplate/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeboilerplate; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.KeyEvent; 6 | 7 | import com.facebook.react.LifecycleState; 8 | import com.facebook.react.ReactInstanceManager; 9 | import com.facebook.react.ReactRootView; 10 | import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; 11 | import com.facebook.react.shell.MainReactPackage; 12 | import com.facebook.soloader.SoLoader; 13 | 14 | public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler { 15 | 16 | private ReactInstanceManager mReactInstanceManager; 17 | private ReactRootView mReactRootView; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | mReactRootView = new ReactRootView(this); 23 | 24 | mReactInstanceManager = ReactInstanceManager.builder() 25 | .setApplication(getApplication()) 26 | .setBundleAssetName("index.android.bundle") 27 | .setJSMainModuleName("index.android") 28 | .addPackage(new MainReactPackage()) 29 | .setUseDeveloperSupport(BuildConfig.DEBUG) 30 | .setInitialLifecycleState(LifecycleState.RESUMED) 31 | .build(); 32 | 33 | mReactRootView.startReactApplication(mReactInstanceManager, "ReactNativeBoilerplate", null); 34 | 35 | setContentView(mReactRootView); 36 | } 37 | 38 | @Override 39 | public boolean onKeyUp(int keyCode, KeyEvent event) { 40 | if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { 41 | mReactInstanceManager.showDevOptionsDialog(); 42 | return true; 43 | } 44 | return super.onKeyUp(keyCode, event); 45 | } 46 | 47 | @Override 48 | public void onBackPressed() { 49 | if (mReactInstanceManager != null) { 50 | mReactInstanceManager.onBackPressed(); 51 | } else { 52 | super.onBackPressed(); 53 | } 54 | } 55 | 56 | @Override 57 | public void invokeDefaultOnBackPressed() { 58 | super.onBackPressed(); 59 | } 60 | 61 | @Override 62 | protected void onPause() { 63 | super.onPause(); 64 | 65 | if (mReactInstanceManager != null) { 66 | mReactInstanceManager.onPause(); 67 | } 68 | } 69 | 70 | @Override 71 | protected void onResume() { 72 | super.onResume(); 73 | 74 | if (mReactInstanceManager != null) { 75 | mReactInstanceManager.onResume(this); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ReactNativeBoilerplate 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremiahrhall/react-native-redux-todo/6d489be1ce504d3ce55d7d8d1d62f819520058e6/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ReactNativeBoilerplate' 2 | 3 | include ':app' 4 | -------------------------------------------------------------------------------- /index.android.js: -------------------------------------------------------------------------------- 1 | // TODO Android 2 | 3 | /** 4 | * Sample React Native App 5 | * https://github.com/facebook/react-native 6 | */ 7 | 'use strict'; 8 | 9 | var React = require('react-native'); 10 | var { 11 | AppRegistry, 12 | StyleSheet, 13 | Text, 14 | View, 15 | } = React; 16 | 17 | var ReactNativeBoilerplate = React.createClass({ 18 | render: function() { 19 | return ( 20 | 21 | 22 | Welcome to React Native! 23 | 24 | 25 | To get started, edit index.android.js 26 | 27 | 28 | Shake or press menu button for dev menu 29 | 30 | 31 | ); 32 | } 33 | }); 34 | 35 | var styles = StyleSheet.create({ 36 | container: { 37 | flex: 1, 38 | justifyContent: 'center', 39 | alignItems: 'center', 40 | backgroundColor: '#F5FCFF', 41 | }, 42 | welcome: { 43 | fontSize: 20, 44 | textAlign: 'center', 45 | margin: 10, 46 | }, 47 | instructions: { 48 | textAlign: 'center', 49 | color: '#333333', 50 | marginBottom: 5, 51 | }, 52 | }); 53 | 54 | AppRegistry.registerComponent('ReactNativeBoilerplate', () => ReactNativeBoilerplate); 55 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | 3 | import App from './js/App.js'; 4 | 5 | AppRegistry.registerComponent('ReactNativeBoilerplate', () => App); 6 | -------------------------------------------------------------------------------- /installPlugins.js: -------------------------------------------------------------------------------- 1 | var async = require('async'); 2 | var ChildProcess = require('child_process'); 3 | var _ = require('lodash'); 4 | var a = [ 5 | "transform-strict-mode", 6 | "transform-es2015-arrow-functions", 7 | "transform-es2015-block-scoping", 8 | "transform-es2015-block-scoped-functions", 9 | "transform-es2015-classes", 10 | "transform-es2015-computed-properties", 11 | "transform-es2015-constants", 12 | "transform-es2015-destructuring", 13 | "transform-es2015-for-of", 14 | "transform-es2015-literals", 15 | "transform-es2015-modules-commonjs", 16 | "transform-es2015-object-super", 17 | "transform-es2015-parameters", 18 | "transform-es2015-shorthand-properties", 19 | "transform-es2015-spread", 20 | "transform-es2015-sticky-regex", 21 | "transform-es2015-template-literals", 22 | "transform-es2015-typeof-symbol", 23 | "transform-es2015-unicode-regex", 24 | "transform-exponentiation-operator", 25 | "transform-object-rest-spread", 26 | "transform-class-properties", 27 | "transform-react-display-name", 28 | "transform-react-jsx", 29 | "transform-react-inline-elements", 30 | "transform-react-display-name", 31 | "syntax-flow", 32 | "syntax-jsx", 33 | "transform-flow-strip-types" 34 | ]; 35 | 36 | var es2015preset = { 37 | "transform-es2015-template-literals": "^6.0.2", 38 | "transform-es2015-literals": "^6.0.2", 39 | "transform-es2015-function-name": "^6.0.2", 40 | "transform-es2015-arrow-functions": "^6.0.2", 41 | "transform-es2015-block-scoped-functions": "^6.0.2", 42 | "transform-es2015-classes": "^6.0.8", 43 | "transform-es2015-object-super": "^6.0.2", 44 | "transform-es2015-shorthand-properties": "^6.0.2", 45 | "transform-es2015-computed-properties": "^6.0.2", 46 | "transform-es2015-for-of": "^6.0.2", 47 | "transform-es2015-sticky-regex": "^6.0.2", 48 | "transform-es2015-unicode-regex": "^6.0.2", 49 | "transform-es2015-constants": "^6.0.2", 50 | "transform-es2015-spread": "^6.0.2", 51 | "transform-es2015-parameters": "^6.0.2", 52 | "transform-es2015-destructuring": "^6.0.2", 53 | "transform-es2015-block-scoping": "^6.0.2", 54 | "transform-es2015-typeof-symbol": "^6.0.2", 55 | "transform-es2015-modules-commonjs": "^6.0.2", 56 | "transform-regenerator": "^6.0.8" 57 | }; 58 | 59 | var reactPreset = { 60 | "syntax-flow": "^6.0.2", 61 | "syntax-jsx": "^6.0.2", 62 | "transform-react-jsx": "^6.0.2", 63 | "transform-flow-strip-types": "^6.0.2" 64 | }; 65 | 66 | var comList = a.concat(_.keys(es2015preset).concat(_.keys(reactPreset))); 67 | 68 | var combined = _.keys(_.reduce(comList, function(result, v, k) { 69 | result[v] = true; 70 | return result; 71 | }, {})); 72 | 73 | async.eachSeries(combined, function(plugin, cb) { 74 | console.log('Starting ', plugin); 75 | var child = ChildProcess.exec('npm install --save babel-plugin-' + plugin, { 76 | env: _.extend(process.env, {}) 77 | }, function(err, stdout, stderr) { 78 | if (err) { 79 | console.log('Error: ', err); 80 | cb(err); 81 | } 82 | console.log('Completed install of ' + plugin) 83 | cb(); 84 | }); 85 | 86 | child.stdout.pipe(process.stdout); 87 | }, function(err) { 88 | console.log('Finished with ', err); 89 | }) 90 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; }; 11 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 12 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 13 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 14 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 15 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 16 | 00E356F31AD99517003FC87E /* ReactNativeBoilerplateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ReactNativeBoilerplateTests.m */; }; 17 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 18 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 19 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; 20 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 21 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 22 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 23 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 24 | 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 25 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 26 | 89AE8B6B1C27495C00690AC1 /* libART.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89AE8B601C27495500690AC1 /* libART.a */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 33 | proxyType = 2; 34 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 35 | remoteInfo = RCTActionSheet; 36 | }; 37 | 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 40 | proxyType = 2; 41 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 42 | remoteInfo = RCTGeolocation; 43 | }; 44 | 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 47 | proxyType = 2; 48 | remoteGlobalIDString = 58B5115D1A9E6B3D00147676; 49 | remoteInfo = RCTImage; 50 | }; 51 | 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { 52 | isa = PBXContainerItemProxy; 53 | containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 54 | proxyType = 2; 55 | remoteGlobalIDString = 58B511DB1A9E6C8500147676; 56 | remoteInfo = RCTNetwork; 57 | }; 58 | 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { 59 | isa = PBXContainerItemProxy; 60 | containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 61 | proxyType = 2; 62 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; 63 | remoteInfo = RCTVibration; 64 | }; 65 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { 66 | isa = PBXContainerItemProxy; 67 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; 68 | proxyType = 1; 69 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A; 70 | remoteInfo = ReactNativeBoilerplate; 71 | }; 72 | 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { 73 | isa = PBXContainerItemProxy; 74 | containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; 75 | proxyType = 2; 76 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 77 | remoteInfo = RCTSettings; 78 | }; 79 | 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { 80 | isa = PBXContainerItemProxy; 81 | containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; 82 | proxyType = 2; 83 | remoteGlobalIDString = 3C86DF461ADF2C930047B81A; 84 | remoteInfo = RCTWebSocket; 85 | }; 86 | 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { 87 | isa = PBXContainerItemProxy; 88 | containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; 89 | proxyType = 2; 90 | remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; 91 | remoteInfo = React; 92 | }; 93 | 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { 94 | isa = PBXContainerItemProxy; 95 | containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; 96 | proxyType = 2; 97 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 98 | remoteInfo = RCTLinking; 99 | }; 100 | 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { 101 | isa = PBXContainerItemProxy; 102 | containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 103 | proxyType = 2; 104 | remoteGlobalIDString = 58B5119B1A9E6C1200147676; 105 | remoteInfo = RCTText; 106 | }; 107 | 89AE8B5F1C27495500690AC1 /* PBXContainerItemProxy */ = { 108 | isa = PBXContainerItemProxy; 109 | containerPortal = 89AE8B5B1C27495500690AC1 /* ART.xcodeproj */; 110 | proxyType = 2; 111 | remoteGlobalIDString = 0CF68AC11AF0540F00FF9E5C; 112 | remoteInfo = ART; 113 | }; 114 | /* End PBXContainerItemProxy section */ 115 | 116 | /* Begin PBXFileReference section */ 117 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 118 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; 119 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; 120 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 121 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 122 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 123 | 00E356EE1AD99517003FC87E /* ReactNativeBoilerplateTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactNativeBoilerplateTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 124 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 125 | 00E356F21AD99517003FC87E /* ReactNativeBoilerplateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativeBoilerplateTests.m; sourceTree = ""; }; 126 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 127 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 128 | 13B07F961A680F5B00A75B9A /* ReactNativeBoilerplate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactNativeBoilerplate.app; sourceTree = BUILT_PRODUCTS_DIR; }; 129 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ReactNativeBoilerplate/AppDelegate.h; sourceTree = ""; }; 130 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ReactNativeBoilerplate/AppDelegate.m; sourceTree = ""; }; 131 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 132 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactNativeBoilerplate/Images.xcassets; sourceTree = ""; }; 133 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactNativeBoilerplate/Info.plist; sourceTree = ""; }; 134 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ReactNativeBoilerplate/main.m; sourceTree = ""; }; 135 | 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 136 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 137 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 138 | 89AE8B5B1C27495500690AC1 /* ART.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ART.xcodeproj; path = "../node_modules/react-native/Libraries/ART/ART.xcodeproj"; sourceTree = ""; }; 139 | /* End PBXFileReference section */ 140 | 141 | /* Begin PBXFrameworksBuildPhase section */ 142 | 00E356EB1AD99517003FC87E /* Frameworks */ = { 143 | isa = PBXFrameworksBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 150 | isa = PBXFrameworksBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | 89AE8B6B1C27495C00690AC1 /* libART.a in Frameworks */, 154 | 146834051AC3E58100842450 /* libReact.a in Frameworks */, 155 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 156 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 157 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 158 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 159 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 160 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, 161 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 162 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 163 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXFrameworksBuildPhase section */ 168 | 169 | /* Begin PBXGroup section */ 170 | 00C302A81ABCB8CE00DB3ED1 /* Products */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, 174 | ); 175 | name = Products; 176 | sourceTree = ""; 177 | }; 178 | 00C302B61ABCB90400DB3ED1 /* Products */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, 182 | ); 183 | name = Products; 184 | sourceTree = ""; 185 | }; 186 | 00C302BC1ABCB91800DB3ED1 /* Products */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 00C302D41ABCB9D200DB3ED1 /* Products */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 198 | ); 199 | name = Products; 200 | sourceTree = ""; 201 | }; 202 | 00C302E01ABCB9EE00DB3ED1 /* Products */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, 206 | ); 207 | name = Products; 208 | sourceTree = ""; 209 | }; 210 | 00E356EF1AD99517003FC87E /* ReactNativeBoilerplateTests */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 00E356F21AD99517003FC87E /* ReactNativeBoilerplateTests.m */, 214 | 00E356F01AD99517003FC87E /* Supporting Files */, 215 | ); 216 | path = ReactNativeBoilerplateTests; 217 | sourceTree = ""; 218 | }; 219 | 00E356F01AD99517003FC87E /* Supporting Files */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 00E356F11AD99517003FC87E /* Info.plist */, 223 | ); 224 | name = "Supporting Files"; 225 | sourceTree = ""; 226 | }; 227 | 139105B71AF99BAD00B5F7CC /* Products */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, 231 | ); 232 | name = Products; 233 | sourceTree = ""; 234 | }; 235 | 139FDEE71B06529A00C62182 /* Products */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 239 | ); 240 | name = Products; 241 | sourceTree = ""; 242 | }; 243 | 13B07FAE1A68108700A75B9A /* ReactNativeBoilerplate */ = { 244 | isa = PBXGroup; 245 | children = ( 246 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 247 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 248 | 13B07FB01A68108700A75B9A /* AppDelegate.m */, 249 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 250 | 13B07FB61A68108700A75B9A /* Info.plist */, 251 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 252 | 13B07FB71A68108700A75B9A /* main.m */, 253 | ); 254 | name = ReactNativeBoilerplate; 255 | sourceTree = ""; 256 | }; 257 | 146834001AC3E56700842450 /* Products */ = { 258 | isa = PBXGroup; 259 | children = ( 260 | 146834041AC3E56700842450 /* libReact.a */, 261 | ); 262 | name = Products; 263 | sourceTree = ""; 264 | }; 265 | 78C398B11ACF4ADC00677621 /* Products */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, 269 | ); 270 | name = Products; 271 | sourceTree = ""; 272 | }; 273 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | 89AE8B5B1C27495500690AC1 /* ART.xcodeproj */, 277 | 146833FF1AC3E56700842450 /* React.xcodeproj */, 278 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, 279 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 280 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 281 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, 282 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, 283 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, 284 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 285 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 286 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, 287 | ); 288 | name = Libraries; 289 | sourceTree = ""; 290 | }; 291 | 832341B11AAA6A8300B99B32 /* Products */ = { 292 | isa = PBXGroup; 293 | children = ( 294 | 832341B51AAA6A8300B99B32 /* libRCTText.a */, 295 | ); 296 | name = Products; 297 | sourceTree = ""; 298 | }; 299 | 83CBB9F61A601CBA00E9B192 = { 300 | isa = PBXGroup; 301 | children = ( 302 | 13B07FAE1A68108700A75B9A /* ReactNativeBoilerplate */, 303 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 304 | 00E356EF1AD99517003FC87E /* ReactNativeBoilerplateTests */, 305 | 83CBBA001A601CBA00E9B192 /* Products */, 306 | ); 307 | indentWidth = 2; 308 | sourceTree = ""; 309 | tabWidth = 2; 310 | }; 311 | 83CBBA001A601CBA00E9B192 /* Products */ = { 312 | isa = PBXGroup; 313 | children = ( 314 | 13B07F961A680F5B00A75B9A /* ReactNativeBoilerplate.app */, 315 | 00E356EE1AD99517003FC87E /* ReactNativeBoilerplateTests.xctest */, 316 | ); 317 | name = Products; 318 | sourceTree = ""; 319 | }; 320 | 89AE8B5C1C27495500690AC1 /* Products */ = { 321 | isa = PBXGroup; 322 | children = ( 323 | 89AE8B601C27495500690AC1 /* libART.a */, 324 | ); 325 | name = Products; 326 | sourceTree = ""; 327 | }; 328 | /* End PBXGroup section */ 329 | 330 | /* Begin PBXNativeTarget section */ 331 | 00E356ED1AD99517003FC87E /* ReactNativeBoilerplateTests */ = { 332 | isa = PBXNativeTarget; 333 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ReactNativeBoilerplateTests" */; 334 | buildPhases = ( 335 | 00E356EA1AD99517003FC87E /* Sources */, 336 | 00E356EB1AD99517003FC87E /* Frameworks */, 337 | 00E356EC1AD99517003FC87E /* Resources */, 338 | ); 339 | buildRules = ( 340 | ); 341 | dependencies = ( 342 | 00E356F51AD99517003FC87E /* PBXTargetDependency */, 343 | ); 344 | name = ReactNativeBoilerplateTests; 345 | productName = ReactNativeBoilerplateTests; 346 | productReference = 00E356EE1AD99517003FC87E /* ReactNativeBoilerplateTests.xctest */; 347 | productType = "com.apple.product-type.bundle.unit-test"; 348 | }; 349 | 13B07F861A680F5B00A75B9A /* ReactNativeBoilerplate */ = { 350 | isa = PBXNativeTarget; 351 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeBoilerplate" */; 352 | buildPhases = ( 353 | 13B07F871A680F5B00A75B9A /* Sources */, 354 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 355 | 13B07F8E1A680F5B00A75B9A /* Resources */, 356 | ); 357 | buildRules = ( 358 | ); 359 | dependencies = ( 360 | ); 361 | name = ReactNativeBoilerplate; 362 | productName = "Hello World"; 363 | productReference = 13B07F961A680F5B00A75B9A /* ReactNativeBoilerplate.app */; 364 | productType = "com.apple.product-type.application"; 365 | }; 366 | /* End PBXNativeTarget section */ 367 | 368 | /* Begin PBXProject section */ 369 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 370 | isa = PBXProject; 371 | attributes = { 372 | LastUpgradeCheck = 0610; 373 | ORGANIZATIONNAME = Facebook; 374 | TargetAttributes = { 375 | 00E356ED1AD99517003FC87E = { 376 | CreatedOnToolsVersion = 6.2; 377 | TestTargetID = 13B07F861A680F5B00A75B9A; 378 | }; 379 | }; 380 | }; 381 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNativeBoilerplate" */; 382 | compatibilityVersion = "Xcode 3.2"; 383 | developmentRegion = English; 384 | hasScannedForEncodings = 0; 385 | knownRegions = ( 386 | en, 387 | Base, 388 | ); 389 | mainGroup = 83CBB9F61A601CBA00E9B192; 390 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 391 | projectDirPath = ""; 392 | projectReferences = ( 393 | { 394 | ProductGroup = 89AE8B5C1C27495500690AC1 /* Products */; 395 | ProjectRef = 89AE8B5B1C27495500690AC1 /* ART.xcodeproj */; 396 | }, 397 | { 398 | ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; 399 | ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 400 | }, 401 | { 402 | ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; 403 | ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 404 | }, 405 | { 406 | ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; 407 | ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 408 | }, 409 | { 410 | ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; 411 | ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; 412 | }, 413 | { 414 | ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; 415 | ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 416 | }, 417 | { 418 | ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; 419 | ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; 420 | }, 421 | { 422 | ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; 423 | ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 424 | }, 425 | { 426 | ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; 427 | ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 428 | }, 429 | { 430 | ProductGroup = 139FDEE71B06529A00C62182 /* Products */; 431 | ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; 432 | }, 433 | { 434 | ProductGroup = 146834001AC3E56700842450 /* Products */; 435 | ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; 436 | }, 437 | ); 438 | projectRoot = ""; 439 | targets = ( 440 | 13B07F861A680F5B00A75B9A /* ReactNativeBoilerplate */, 441 | 00E356ED1AD99517003FC87E /* ReactNativeBoilerplateTests */, 442 | ); 443 | }; 444 | /* End PBXProject section */ 445 | 446 | /* Begin PBXReferenceProxy section */ 447 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { 448 | isa = PBXReferenceProxy; 449 | fileType = archive.ar; 450 | path = libRCTActionSheet.a; 451 | remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; 452 | sourceTree = BUILT_PRODUCTS_DIR; 453 | }; 454 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { 455 | isa = PBXReferenceProxy; 456 | fileType = archive.ar; 457 | path = libRCTGeolocation.a; 458 | remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; 459 | sourceTree = BUILT_PRODUCTS_DIR; 460 | }; 461 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { 462 | isa = PBXReferenceProxy; 463 | fileType = archive.ar; 464 | path = libRCTImage.a; 465 | remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; 466 | sourceTree = BUILT_PRODUCTS_DIR; 467 | }; 468 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { 469 | isa = PBXReferenceProxy; 470 | fileType = archive.ar; 471 | path = libRCTNetwork.a; 472 | remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; 473 | sourceTree = BUILT_PRODUCTS_DIR; 474 | }; 475 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { 476 | isa = PBXReferenceProxy; 477 | fileType = archive.ar; 478 | path = libRCTVibration.a; 479 | remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; 480 | sourceTree = BUILT_PRODUCTS_DIR; 481 | }; 482 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { 483 | isa = PBXReferenceProxy; 484 | fileType = archive.ar; 485 | path = libRCTSettings.a; 486 | remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; 487 | sourceTree = BUILT_PRODUCTS_DIR; 488 | }; 489 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { 490 | isa = PBXReferenceProxy; 491 | fileType = archive.ar; 492 | path = libRCTWebSocket.a; 493 | remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; 494 | sourceTree = BUILT_PRODUCTS_DIR; 495 | }; 496 | 146834041AC3E56700842450 /* libReact.a */ = { 497 | isa = PBXReferenceProxy; 498 | fileType = archive.ar; 499 | path = libReact.a; 500 | remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; 501 | sourceTree = BUILT_PRODUCTS_DIR; 502 | }; 503 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { 504 | isa = PBXReferenceProxy; 505 | fileType = archive.ar; 506 | path = libRCTLinking.a; 507 | remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; 508 | sourceTree = BUILT_PRODUCTS_DIR; 509 | }; 510 | 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { 511 | isa = PBXReferenceProxy; 512 | fileType = archive.ar; 513 | path = libRCTText.a; 514 | remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; 515 | sourceTree = BUILT_PRODUCTS_DIR; 516 | }; 517 | 89AE8B601C27495500690AC1 /* libART.a */ = { 518 | isa = PBXReferenceProxy; 519 | fileType = archive.ar; 520 | path = libART.a; 521 | remoteRef = 89AE8B5F1C27495500690AC1 /* PBXContainerItemProxy */; 522 | sourceTree = BUILT_PRODUCTS_DIR; 523 | }; 524 | /* End PBXReferenceProxy section */ 525 | 526 | /* Begin PBXResourcesBuildPhase section */ 527 | 00E356EC1AD99517003FC87E /* Resources */ = { 528 | isa = PBXResourcesBuildPhase; 529 | buildActionMask = 2147483647; 530 | files = ( 531 | ); 532 | runOnlyForDeploymentPostprocessing = 0; 533 | }; 534 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 535 | isa = PBXResourcesBuildPhase; 536 | buildActionMask = 2147483647; 537 | files = ( 538 | 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */, 539 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 540 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 541 | ); 542 | runOnlyForDeploymentPostprocessing = 0; 543 | }; 544 | /* End PBXResourcesBuildPhase section */ 545 | 546 | /* Begin PBXSourcesBuildPhase section */ 547 | 00E356EA1AD99517003FC87E /* Sources */ = { 548 | isa = PBXSourcesBuildPhase; 549 | buildActionMask = 2147483647; 550 | files = ( 551 | 00E356F31AD99517003FC87E /* ReactNativeBoilerplateTests.m in Sources */, 552 | ); 553 | runOnlyForDeploymentPostprocessing = 0; 554 | }; 555 | 13B07F871A680F5B00A75B9A /* Sources */ = { 556 | isa = PBXSourcesBuildPhase; 557 | buildActionMask = 2147483647; 558 | files = ( 559 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 560 | 13B07FC11A68108700A75B9A /* main.m in Sources */, 561 | ); 562 | runOnlyForDeploymentPostprocessing = 0; 563 | }; 564 | /* End PBXSourcesBuildPhase section */ 565 | 566 | /* Begin PBXTargetDependency section */ 567 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { 568 | isa = PBXTargetDependency; 569 | target = 13B07F861A680F5B00A75B9A /* ReactNativeBoilerplate */; 570 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; 571 | }; 572 | /* End PBXTargetDependency section */ 573 | 574 | /* Begin PBXVariantGroup section */ 575 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { 576 | isa = PBXVariantGroup; 577 | children = ( 578 | 13B07FB21A68108700A75B9A /* Base */, 579 | ); 580 | name = LaunchScreen.xib; 581 | path = ReactNativeBoilerplate; 582 | sourceTree = ""; 583 | }; 584 | /* End PBXVariantGroup section */ 585 | 586 | /* Begin XCBuildConfiguration section */ 587 | 00E356F61AD99517003FC87E /* Debug */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | BUNDLE_LOADER = "$(TEST_HOST)"; 591 | FRAMEWORK_SEARCH_PATHS = ( 592 | "$(SDKROOT)/Developer/Library/Frameworks", 593 | "$(inherited)", 594 | ); 595 | GCC_PREPROCESSOR_DEFINITIONS = ( 596 | "DEBUG=1", 597 | "$(inherited)", 598 | ); 599 | INFOPLIST_FILE = ReactNativeBoilerplateTests/Info.plist; 600 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 601 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 602 | PRODUCT_NAME = "$(TARGET_NAME)"; 603 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactNativeBoilerplate.app/ReactNativeBoilerplate"; 604 | }; 605 | name = Debug; 606 | }; 607 | 00E356F71AD99517003FC87E /* Release */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | BUNDLE_LOADER = "$(TEST_HOST)"; 611 | COPY_PHASE_STRIP = NO; 612 | FRAMEWORK_SEARCH_PATHS = ( 613 | "$(SDKROOT)/Developer/Library/Frameworks", 614 | "$(inherited)", 615 | ); 616 | INFOPLIST_FILE = ReactNativeBoilerplateTests/Info.plist; 617 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 618 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 619 | PRODUCT_NAME = "$(TARGET_NAME)"; 620 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactNativeBoilerplate.app/ReactNativeBoilerplate"; 621 | }; 622 | name = Release; 623 | }; 624 | 13B07F941A680F5B00A75B9A /* Debug */ = { 625 | isa = XCBuildConfiguration; 626 | buildSettings = { 627 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 628 | DEAD_CODE_STRIPPING = NO; 629 | HEADER_SEARCH_PATHS = ( 630 | "$(inherited)", 631 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 632 | "$(SRCROOT)/../node_modules/react-native/React/**", 633 | ); 634 | INFOPLIST_FILE = ReactNativeBoilerplate/Info.plist; 635 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 636 | OTHER_LDFLAGS = "-ObjC"; 637 | PRODUCT_NAME = ReactNativeBoilerplate; 638 | }; 639 | name = Debug; 640 | }; 641 | 13B07F951A680F5B00A75B9A /* Release */ = { 642 | isa = XCBuildConfiguration; 643 | buildSettings = { 644 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 645 | HEADER_SEARCH_PATHS = ( 646 | "$(inherited)", 647 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 648 | "$(SRCROOT)/../node_modules/react-native/React/**", 649 | ); 650 | INFOPLIST_FILE = ReactNativeBoilerplate/Info.plist; 651 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 652 | OTHER_LDFLAGS = "-ObjC"; 653 | PRODUCT_NAME = ReactNativeBoilerplate; 654 | }; 655 | name = Release; 656 | }; 657 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 658 | isa = XCBuildConfiguration; 659 | buildSettings = { 660 | ALWAYS_SEARCH_USER_PATHS = NO; 661 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 662 | CLANG_CXX_LIBRARY = "libc++"; 663 | CLANG_ENABLE_MODULES = YES; 664 | CLANG_ENABLE_OBJC_ARC = YES; 665 | CLANG_WARN_BOOL_CONVERSION = YES; 666 | CLANG_WARN_CONSTANT_CONVERSION = YES; 667 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 668 | CLANG_WARN_EMPTY_BODY = YES; 669 | CLANG_WARN_ENUM_CONVERSION = YES; 670 | CLANG_WARN_INT_CONVERSION = YES; 671 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 672 | CLANG_WARN_UNREACHABLE_CODE = YES; 673 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 674 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 675 | COPY_PHASE_STRIP = NO; 676 | ENABLE_STRICT_OBJC_MSGSEND = YES; 677 | GCC_C_LANGUAGE_STANDARD = gnu99; 678 | GCC_DYNAMIC_NO_PIC = NO; 679 | GCC_OPTIMIZATION_LEVEL = 0; 680 | GCC_PREPROCESSOR_DEFINITIONS = ( 681 | "DEBUG=1", 682 | "$(inherited)", 683 | ); 684 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 685 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 686 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 687 | GCC_WARN_UNDECLARED_SELECTOR = YES; 688 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 689 | GCC_WARN_UNUSED_FUNCTION = YES; 690 | GCC_WARN_UNUSED_VARIABLE = YES; 691 | HEADER_SEARCH_PATHS = ( 692 | "$(inherited)", 693 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 694 | "$(SRCROOT)/../node_modules/react-native/React/**", 695 | ); 696 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 697 | MTL_ENABLE_DEBUG_INFO = YES; 698 | ONLY_ACTIVE_ARCH = YES; 699 | SDKROOT = iphoneos; 700 | }; 701 | name = Debug; 702 | }; 703 | 83CBBA211A601CBA00E9B192 /* Release */ = { 704 | isa = XCBuildConfiguration; 705 | buildSettings = { 706 | ALWAYS_SEARCH_USER_PATHS = NO; 707 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 708 | CLANG_CXX_LIBRARY = "libc++"; 709 | CLANG_ENABLE_MODULES = YES; 710 | CLANG_ENABLE_OBJC_ARC = YES; 711 | CLANG_WARN_BOOL_CONVERSION = YES; 712 | CLANG_WARN_CONSTANT_CONVERSION = YES; 713 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 714 | CLANG_WARN_EMPTY_BODY = YES; 715 | CLANG_WARN_ENUM_CONVERSION = YES; 716 | CLANG_WARN_INT_CONVERSION = YES; 717 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 718 | CLANG_WARN_UNREACHABLE_CODE = YES; 719 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 720 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 721 | COPY_PHASE_STRIP = YES; 722 | ENABLE_NS_ASSERTIONS = NO; 723 | ENABLE_STRICT_OBJC_MSGSEND = YES; 724 | GCC_C_LANGUAGE_STANDARD = gnu99; 725 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 726 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 727 | GCC_WARN_UNDECLARED_SELECTOR = YES; 728 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 729 | GCC_WARN_UNUSED_FUNCTION = YES; 730 | GCC_WARN_UNUSED_VARIABLE = YES; 731 | HEADER_SEARCH_PATHS = ( 732 | "$(inherited)", 733 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 734 | "$(SRCROOT)/../node_modules/react-native/React/**", 735 | ); 736 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 737 | MTL_ENABLE_DEBUG_INFO = NO; 738 | SDKROOT = iphoneos; 739 | VALIDATE_PRODUCT = YES; 740 | }; 741 | name = Release; 742 | }; 743 | /* End XCBuildConfiguration section */ 744 | 745 | /* Begin XCConfigurationList section */ 746 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ReactNativeBoilerplateTests" */ = { 747 | isa = XCConfigurationList; 748 | buildConfigurations = ( 749 | 00E356F61AD99517003FC87E /* Debug */, 750 | 00E356F71AD99517003FC87E /* Release */, 751 | ); 752 | defaultConfigurationIsVisible = 0; 753 | defaultConfigurationName = Release; 754 | }; 755 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeBoilerplate" */ = { 756 | isa = XCConfigurationList; 757 | buildConfigurations = ( 758 | 13B07F941A680F5B00A75B9A /* Debug */, 759 | 13B07F951A680F5B00A75B9A /* Release */, 760 | ); 761 | defaultConfigurationIsVisible = 0; 762 | defaultConfigurationName = Release; 763 | }; 764 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNativeBoilerplate" */ = { 765 | isa = XCConfigurationList; 766 | buildConfigurations = ( 767 | 83CBBA201A601CBA00E9B192 /* Debug */, 768 | 83CBBA211A601CBA00E9B192 /* Release */, 769 | ); 770 | defaultConfigurationIsVisible = 0; 771 | defaultConfigurationName = Release; 772 | }; 773 | /* End XCConfigurationList section */ 774 | }; 775 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 776 | } 777 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate.xcodeproj/xcshareddata/xcschemes/ReactNativeBoilerplate.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import "RCTRootView.h" 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | NSURL *jsCodeLocation; 19 | 20 | /** 21 | * Loading JavaScript code - uncomment the one you want. 22 | * 23 | * OPTION 1 24 | * Load from development server. Start the server from the repository root: 25 | * 26 | * $ npm start 27 | * 28 | * To run on device, change `localhost` to the IP address of your computer 29 | * (you can get this by typing `ifconfig` into the terminal and selecting the 30 | * `inet` value under `en0:`) and make sure your computer and iOS device are 31 | * on the same Wi-Fi network. 32 | */ 33 | 34 | jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; 35 | 36 | /** 37 | * OPTION 2 38 | * Load from pre-bundled file on disk. To re-generate the static bundle 39 | * from the root of your project directory, run 40 | * 41 | * $ react-native bundle --minify 42 | * 43 | * see http://facebook.github.io/react-native/docs/runningondevice.html 44 | */ 45 | 46 | // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 47 | 48 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 49 | moduleName:@"ReactNativeBoilerplate" 50 | initialProperties:nil 51 | launchOptions:launchOptions]; 52 | 53 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 54 | UIViewController *rootViewController = [[UIViewController alloc] init]; 55 | rootViewController.view = rootView; 56 | self.window.rootViewController = rootViewController; 57 | [self.window makeKeyAndVisible]; 58 | return YES; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSAllowsArbitraryLoads 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplate/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplateTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/ReactNativeBoilerplateTests/ReactNativeBoilerplateTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import "RCTLog.h" 14 | #import "RCTRootView.h" 15 | 16 | #define TIMEOUT_SECONDS 240 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface ReactNativeBoilerplateTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation ReactNativeBoilerplateTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ios/main.jsbundle: -------------------------------------------------------------------------------- 1 | // Offline JS 2 | // To re-generate the offline bundle, run this from the root of your project: 3 | // 4 | // $ react-native bundle --minify 5 | // 6 | // See http://facebook.github.io/react-native/docs/runningondevice.html for more details. 7 | 8 | throw new Error('Offline JS file is empty. See iOS/main.jsbundle for instructions'); 9 | -------------------------------------------------------------------------------- /jestSupport/scriptPreprocess.js: -------------------------------------------------------------------------------- 1 | var babel = require('babel-core'); 2 | 3 | module.exports = { 4 | process: function (src, filename) { 5 | var result = babel.transform(src, { 6 | filename: filename 7 | }); 8 | 9 | return result.code; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /js/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react-native'; 2 | import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; 3 | import { Provider } from 'react-redux/native'; 4 | import thunk from 'redux-thunk'; 5 | import { persistStore } from 'redux-persist'; 6 | 7 | import AppContainer from './containers/AppContainer'; 8 | import DispatchLogger from './middleware/DispatchLogger'; 9 | 10 | import reducers from './reducers'; 11 | import persistenceTransformer from './util/persistenceTransformer'; 12 | 13 | const { AsyncStorage } = React; 14 | 15 | const store = compose( 16 | applyMiddleware(thunk, DispatchLogger) 17 | )(createStore)(combineReducers(reducers)); 18 | 19 | persistStore(store, { storage: AsyncStorage, transforms: [ persistenceTransformer ] }); 20 | 21 | export default class App extends Component { 22 | 23 | render() { 24 | return ( 25 | 26 | { () => } 27 | 28 | ); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /js/actionCreators/NavigationActionCreators.js: -------------------------------------------------------------------------------- 1 | 2 | import NavigationActionTypes from '../constants/NavigationActionTypes'; 3 | 4 | let dispatchRouteAction = (actionType, navigatorKey, componentKey, sceneConfig) => { 5 | return (dispatch) => { 6 | return dispatch({ 7 | type: actionType, 8 | navigatorKey: navigatorKey, 9 | componentKey: componentKey, 10 | sceneConfig: sceneConfig 11 | }); 12 | }; 13 | }; 14 | 15 | export function jumpBack(navigatorKey) { 16 | return (dispatch) => { 17 | return dispatch({ 18 | type: NavigationActionTypes.NAVIGATOR_JUMP_BACK, 19 | navigatorKey: navigatorKey 20 | }); 21 | }; 22 | } 23 | 24 | export function jumpForward(navigatorKey, componentKey) { 25 | return (dispatch) => { 26 | return dispatch({ 27 | type: NavigationActionTypes.NAVIGATOR_JUMP_FORWARD, 28 | navigatorKey: navigatorKey 29 | }); 30 | }; 31 | } 32 | 33 | export function jumpTo(navigatorKey, componentKey, sceneConfig) { 34 | return dispatchRouteAction( 35 | NavigationActionTypes.NAVIGATOR_JUMP_TO, 36 | navigatorKey, 37 | componentKey, 38 | sceneConfig 39 | ); 40 | } 41 | 42 | export function push(navigatorKey, componentKey, sceneConfig) { 43 | return dispatchRouteAction( 44 | NavigationActionTypes.NAVIGATOR_PUSH, 45 | navigatorKey, 46 | componentKey, 47 | sceneConfig 48 | ); 49 | } 50 | 51 | export function pop(navigatorKey) { 52 | return (dispatch) => { 53 | return dispatch({ 54 | type: NavigationActionTypes.NAVIGATOR_POP, 55 | navigatorKey: navigatorKey 56 | }); 57 | }; 58 | } 59 | 60 | export function replace(navigatorKey, componentKey, sceneConfig) { 61 | return dispatchRouteAction( 62 | NavigationActionTypes.NAVIGATOR_REPLACE, 63 | navigatorKey, 64 | componentKey, 65 | sceneConfig 66 | ); 67 | } 68 | 69 | export function replaceAtIndex(navigatorKey, componentKey, sceneConfig, index) { 70 | return (dispatch) => { 71 | return dispatch({ 72 | type: NavigationActionTypes.NAVIGATOR_REPLACE_AT_INDEX, 73 | navigatorKey: navigatorKey, 74 | navigateTo: componentKey, 75 | sceneConfig: sceneConfig, 76 | index: index 77 | }); 78 | }; 79 | } 80 | 81 | export function replacePrevious(navigatorKey, componentKey, sceneConfig) { 82 | return dispatchRouteAction( 83 | NavigationActionTypes.NAVIGATOR_REPLACE_PREVIOUS, 84 | navigatorKey, 85 | componentKey, 86 | sceneConfig 87 | ); 88 | } 89 | 90 | export function immediatelyResetRouteStack(navigatorKey, stack) { 91 | return (dispatch) => { 92 | return dispatch({ 93 | type: NavigationActionTypes.NAVIGATOR_IMMEDIATELY_RESET_ROUTE_STACK, 94 | stack: stack 95 | }); 96 | }; 97 | } 98 | 99 | export function popToRoute(navigatorKey, componentKey, sceneConfig) { 100 | return dispatchRouteAction( 101 | NavigationActionTypes.NAVIGATOR_POP_TO_ROUTE, 102 | navigatorKey, 103 | componentKey, 104 | sceneConfig 105 | ); 106 | } 107 | 108 | export function popToTop(navigatorKey) { 109 | return dispatchRouteAction( 110 | NavigationActionTypes.NAVIGATOR_POP_TO_TOP, 111 | navigatorKey 112 | ); 113 | } 114 | 115 | export function removeAction(navigatorKey, action) { 116 | return (dispatch) => { 117 | return dispatch({ 118 | type: NavigationActionTypes.NAVIGATOR_REMOVE_ACTION, 119 | navigatorKey: navigatorKey, 120 | action: action 121 | }); 122 | }; 123 | } 124 | -------------------------------------------------------------------------------- /js/actionCreators/TodoActionCreators.js: -------------------------------------------------------------------------------- 1 | import types from '../constants/TodoActionTypes'; 2 | 3 | export function addTodo(text) { 4 | return (dispatch) => { 5 | return dispatch({ type: types.ADD_TODO, text }); 6 | }; 7 | } 8 | 9 | export function deleteTodo(id) { 10 | return (dispatch) => { 11 | return dispatch({ type: types.DELETE_TODO, id }); 12 | }; 13 | } 14 | 15 | export function editTodo(id, text) { 16 | return (dispatch) => { 17 | return dispatch({ type: types.EDIT_TODO, id, text }); 18 | }; 19 | } 20 | 21 | export function completeTodo(id) { 22 | return (dispatch) => { 23 | return dispatch({ type: types.COMPLETE_TODO, id }); 24 | }; 25 | } 26 | 27 | export function completeAll() { 28 | return (dispatch) => { 29 | return dispatch({ type: types.COMPLETE_ALL }); 30 | }; 31 | } 32 | 33 | export function clearCompleted() { 34 | return (dispatch) => { 35 | return dispatch({ type: types.CLEAR_COMPLETED }); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /js/components/TodoFilterBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import _ from 'lodash'; 3 | 4 | import { FilterLabels, FilterValues, FilterKeys } from '../constants/TodoFilters'; 5 | import { Color } from '../styles'; 6 | 7 | const { 8 | StyleSheet, 9 | View, 10 | Text, 11 | TouchableHighlight, 12 | TextInput, 13 | SegmentedControlIOS, 14 | TabBarIOS 15 | } = React; 16 | 17 | const styles = StyleSheet.create({ 18 | container: { 19 | flex: 1.25, 20 | padding: 8, 21 | flexDirection: 'column', 22 | backgroundColor: Color.raw.darkslateblue.clone().desaturate(0.35).lighten(0.55).rgbString(), 23 | }, 24 | todosLeft: { 25 | flex: 1, 26 | textAlign: 'center', 27 | backgroundColor: Color.raw.darkslateblue.clone().desaturate(0.35).lighten(0.55).rgbString(), 28 | color: Color.rgb.white, 29 | }, 30 | filters: { 31 | flex: 1, 32 | backgroundColor: Color.raw.darkslateblue.clone().desaturate(0.15).lighten(1.5).rgbString(), 33 | borderColor: 'black', 34 | color: 'black', 35 | borderRadius: 5 36 | }, 37 | }); 38 | 39 | const TodoTextInput = React.createClass({ 40 | 41 | propTypes: { 42 | todosLeft: React.PropTypes.number.isRequired, 43 | selectedFilter: React.PropTypes.string.isRequired, 44 | onFilterChange: React.PropTypes.func.isRequired, 45 | }, 46 | 47 | getSegmentedControl() { 48 | return ( 49 | 55 | ); 56 | }, 57 | 58 | render() { 59 | return ( 60 | 61 | 62 | {this.props.todosLeft} {this.props.todosLeft == 1 ? 'item' : 'items'} left 63 | 64 | {this.getSegmentedControl()} 65 | 66 | ); 67 | }, 68 | 69 | }); 70 | 71 | export default TodoTextInput; 72 | -------------------------------------------------------------------------------- /js/components/TodoList.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | 3 | import Immutable from 'immutable'; 4 | 5 | import TodoListItem from './TodoListItem'; 6 | 7 | const { 8 | StyleSheet, 9 | View, 10 | Text, 11 | TouchableHighlight, 12 | TextInput, 13 | ListView 14 | } = React; 15 | 16 | const styles = StyleSheet.create({ 17 | container: { 18 | flex: 10 19 | }, 20 | title: { 21 | 22 | }, 23 | }); 24 | 25 | const TodoList = React.createClass({ 26 | 27 | propTypes: { 28 | todos: React.PropTypes.instanceOf(Immutable.List).isRequired, 29 | addTodo: React.PropTypes.func.isRequired, 30 | deleteTodo: React.PropTypes.func.isRequired, 31 | editTodo: React.PropTypes.func.isRequired, 32 | completeTodo: React.PropTypes.func.isRequired, 33 | completeAll: React.PropTypes.func.isRequired, 34 | clearCompleted: React.PropTypes.func.isRequired, 35 | }, 36 | 37 | render() { 38 | return ( 39 | 40 | 44 | 45 | ); 46 | }, 47 | 48 | getListDataSource() { 49 | return new ListView.DataSource({ 50 | rowHasChanged: (a, b) => a !== b 51 | }).cloneWithRows(this.props.todos.toJS()); 52 | }, 53 | 54 | renderRow(rowData, sectionId, rowId) { 55 | return ( 56 | 63 | ); 64 | }, 65 | 66 | }); 67 | 68 | export default TodoList; 69 | -------------------------------------------------------------------------------- /js/components/TodoListItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import ReactART from 'ReactNativeART'; 3 | 4 | import color from 'color'; 5 | import Swipeout from 'react-native-swipeout'; 6 | 7 | import { Color } from '../styles'; 8 | 9 | const { Surface, Group, Shape } = ReactART; 10 | 11 | const { 12 | StyleSheet, 13 | View, 14 | Text, 15 | TouchableOpacity, 16 | TextInput, 17 | } = React; 18 | 19 | const styles = StyleSheet.create({ 20 | container: { 21 | height: 60, 22 | flex: 6, 23 | backgroundColor: '#FFFFFF', 24 | flexDirection: 'row', 25 | alignItems: 'stretch', 26 | justifyContent: 'space-between', 27 | }, 28 | input: { 29 | flex: 5, 30 | paddingLeft: 12, 31 | paddingRight: 12, 32 | fontSize: 18, 33 | letterSpacing: 0.45, 34 | lineHeight: 40, 35 | }, 36 | switch: { 37 | flex: 1, 38 | }, 39 | switchContainer: { 40 | flex: 1.25, 41 | flexDirection: 'row', 42 | }, 43 | delete: { 44 | flex: 1, 45 | alignItems: 'stretch', 46 | justifyContent: 'space-around', 47 | }, 48 | deleteText: { 49 | textAlign: 'center', 50 | fontSize: 16, 51 | fontWeight: 'bold', 52 | color: '#DD3333' 53 | }, 54 | indicator: { 55 | width: 6, 56 | height: 60 57 | } 58 | }); 59 | 60 | const TodoListItem = React.createClass({ 61 | 62 | propTypes: { 63 | todo: React.PropTypes.object.isRequired, 64 | deleteTodo: React.PropTypes.func.isRequired, 65 | editTodo: React.PropTypes.func.isRequired, 66 | completeTodo: React.PropTypes.func.isRequired, 67 | rowId: React.PropTypes.number.isRequired, 68 | }, 69 | 70 | getInitialState() { 71 | return { 72 | editing: false, 73 | }; 74 | }, 75 | 76 | componentDidUpdate(prevProps, prevState) { 77 | if (prevProps.todo != this.props.todo) { 78 | this.setState({ editing: false }); 79 | } 80 | }, 81 | 82 | getAccentColor() { 83 | return this.props.todo.completed ? Color.rgb.fadedGreen : Color.raw.lightBlue.clone().desaturate(1).rgbString(); 84 | }, 85 | 86 | getSwipeButtons() { 87 | return [ 88 | { 89 | text: 'Delete', 90 | onPress: () => this.deleteTodo(), 91 | type: 'default', 92 | color: Color.rgb.white, 93 | backgroundColor: Color.rgb.fadedRed, 94 | underlayColor: color(this.getAccentColor()).darken(0.2), 95 | } 96 | ]; 97 | }, 98 | 99 | getText() { 100 | if (!this.state.editing) { 101 | return ( 102 | this.setState({ editing: !this.state.editing })}> 103 | {this.props.todo.text} 104 | 105 | ); 106 | } 107 | 108 | return ( 109 | this.setState({ editing: !this.state.editing })} 112 | style={styles.input} 113 | placeholder={"What needs to be done?"} 114 | defaultValue={this.props.todo.text} 115 | maxLength={140} 116 | onSubmitEditing={this.onSubmit} 117 | onChangeText={this.onChange} 118 | /> 119 | ) 120 | }, 121 | 122 | render() { 123 | return ( 124 | 125 | 126 | this.props.completeTodo(this.props.todo.id)}> 127 | 128 | 129 | 130 | 131 | 132 | {this.getText()} 133 | 134 | 135 | ); 136 | }, 137 | 138 | getInitialState() { 139 | return { text: this.props.todo.text }; 140 | }, 141 | 142 | onChange(text) { 143 | this.setState({ text: text }); 144 | }, 145 | 146 | onSubmit() { 147 | this.props.editTodo(this.props.todo.id, this.state.text); 148 | }, 149 | 150 | deleteTodo() { 151 | this.props.deleteTodo(this.props.todo.id); 152 | }, 153 | 154 | }); 155 | 156 | export default TodoListItem; 157 | -------------------------------------------------------------------------------- /js/components/TodoTextInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | 3 | import { Color } from '../styles'; 4 | 5 | const { 6 | StyleSheet, 7 | View, 8 | Text, 9 | TouchableHighlight, 10 | TextInput 11 | } = React; 12 | 13 | const styles = StyleSheet.create({ 14 | container: { 15 | flex: 1, 16 | borderTopWidth: 1, 17 | borderBottomWidth: 1, 18 | borderTopColor: Color.rgb.lightGray, 19 | borderBottomColor: Color.rgb.lightGray, 20 | shadowColor: Color.rgb.lightGray, 21 | backgroundColor: Color.rgb.white, 22 | }, 23 | input: { 24 | flex: 6, 25 | padding: 16 26 | }, 27 | }); 28 | 29 | const TodoTextInput = React.createClass({ 30 | 31 | propTypes: { 32 | addTodo: React.PropTypes.func.isRequired, 33 | }, 34 | 35 | getInitialState() { 36 | return { 37 | text: null 38 | }; 39 | }, 40 | 41 | render() { 42 | return ( 43 | 44 | 52 | 53 | ); 54 | }, 55 | 56 | onChange(text) { 57 | this.setState({ text: text }); 58 | }, 59 | 60 | onSubmit() { 61 | this.props.addTodo(this.state.text); 62 | this.setState({ text: null }); 63 | }, 64 | 65 | }); 66 | 67 | export default TodoTextInput; 68 | -------------------------------------------------------------------------------- /js/constants/NavigationActionTypes.js: -------------------------------------------------------------------------------- 1 | 2 | import keyMirror from '../util/keyMirror'; 3 | 4 | export default keyMirror([ 5 | 'NAVIGATOR_JUMP_BACK', 6 | 'NAVIGATOR_JUMP_FORWARD', 7 | 'NAVIGATOR_JUMP_TO', 8 | 'NAVIGATOR_PUSH', 9 | 'NAVIGATOR_POP', 10 | 'NAVIGATOR_REPLACE', 11 | 'NAVIGATOR_REPLACE_AT_INDEX', 12 | 'NAVIGATOR_REPLACE_PREVIOUS', 13 | 'NAVIGATOR_IMMEDIATELY_RESET_ROUTE_STACK', 14 | 'NAVIGATOR_POP_TO_ROUTE', 15 | 'NAVIGATOR_POP_TO_TOP', 16 | 'NAVIGATOR_REMOVE_ACTION' 17 | ]); 18 | -------------------------------------------------------------------------------- /js/constants/NavigationConstants.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | import Todos from '../containers/Todos'; 4 | 5 | export const ComponentMapping = { 6 | Todos 7 | }; 8 | 9 | export const ComponentKeys = _.keys(ComponentMapping); 10 | -------------------------------------------------------------------------------- /js/constants/NavigatorKeys.js: -------------------------------------------------------------------------------- 1 | 2 | import keyMirror from '../util/keyMirror'; 3 | 4 | export default keyMirror([ 5 | 'ROOT' 6 | ]); 7 | -------------------------------------------------------------------------------- /js/constants/TodoActionTypes.js: -------------------------------------------------------------------------------- 1 | 2 | import keyMirror from '../util/keyMirror'; 3 | 4 | export default keyMirror([ 5 | 'ADD_TODO', 6 | 'DELETE_TODO', 7 | 'EDIT_TODO', 8 | 'COMPLETE_TODO', 9 | 'COMPLETE_ALL', 10 | 'CLEAR_COMPLETED' 11 | ]); 12 | -------------------------------------------------------------------------------- /js/constants/TodoFilters.js: -------------------------------------------------------------------------------- 1 | 2 | import keyMirror from '../util/keyMirror'; 3 | 4 | export const FilterValues = [ 5 | 'SHOW_ALL', 6 | 'SHOW_ACTIVE', 7 | 'SHOW_COMPLETED', 8 | ]; 9 | 10 | export const FilterKeys = keyMirror(FilterValues); 11 | 12 | export const FilterLabels = [ 13 | 'All', 14 | 'Active', 15 | 'Completed' 16 | ]; 17 | -------------------------------------------------------------------------------- /js/containers/AppContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import _ from 'lodash'; 3 | import { bindActionCreators } from 'redux'; 4 | import { connect } from 'react-redux/native'; 5 | 6 | import NavigatorKeys from '../constants/NavigatorKeys'; 7 | 8 | import { jumpForward, jumpBack, pop, push } from '../actionCreators/NavigationActionCreators'; 9 | import { getNavigatorForKey } from '../selectors/NavigationSelectors'; 10 | 11 | import Navigator from './Navigator'; 12 | 13 | const { 14 | StyleSheet, 15 | View, 16 | Text, 17 | TouchableHighlight 18 | } = React; 19 | 20 | const styles = StyleSheet.create({ 21 | container: { 22 | flex: 1, 23 | backgroundColor: '#FFFFFF', 24 | marginTop: 20, 25 | } 26 | }); 27 | 28 | const AppContainer = React.createClass({ 29 | 30 | render() { 31 | return ( 32 | 33 | 34 | 35 | ); 36 | }, 37 | 38 | }); 39 | 40 | export const Component = AppContainer; 41 | 42 | export default connect( 43 | (state) => { 44 | return { navigator: getNavigatorForKey(NavigatorKeys.ROOT) }; 45 | }, 46 | (dispatch) => bindActionCreators({ jumpForward, jumpBack, pop, push }, dispatch) 47 | )(AppContainer); 48 | -------------------------------------------------------------------------------- /js/containers/Navigator.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux/native'; 4 | import Immutable from 'immutable'; 5 | 6 | import { removeAction } from '../actionCreators/NavigationActionCreators'; 7 | import NavigationSelectors from '../selectors/NavigationSelectors'; 8 | import { ComponentMapping } from '../constants/NavigationConstants'; 9 | import NavigatorActionTypes from '../constants/NavigationActionTypes'; 10 | 11 | const { 12 | Navigator 13 | } = React; 14 | 15 | const { 16 | getActionsForNavigatorKey, 17 | getInitialRouteFor, 18 | getSceneConfigFrom, 19 | getTypeFrom, 20 | getComponentKeyFrom 21 | } = NavigationSelectors; 22 | 23 | const NavigatorComponent = React.createClass({ 24 | 25 | propTypes: { 26 | navigatorKey: React.PropTypes.string.isRequired, 27 | navigatorActions: React.PropTypes.instanceOf(Immutable.List), 28 | initialRoute: React.PropTypes.instanceOf(Immutable.Map), 29 | }, 30 | 31 | render() { 32 | return ( 33 | 38 | ); 39 | }, 40 | 41 | renderScene(route, navigator) { 42 | if (!this.props.navigatorActions) { 43 | return null; 44 | } 45 | 46 | let Component = this.getComponentForKey(getComponentKeyFrom(route)); 47 | 48 | if (!Component) { 49 | return ( 50 | null 51 | ); 52 | } 53 | 54 | return ( 55 | 57 | ); 58 | }, 59 | 60 | componentDidUpdate(prevProps, prevState) { 61 | if (!this.props.navigatorActions || this.props.navigatorActions.size == 0) { 62 | return; 63 | } 64 | 65 | let action = this.props.navigatorActions.first(); 66 | 67 | switch (getTypeFrom(action)) { 68 | 69 | case NavigatorActionTypes.NAVIGATOR_JUMP_BACK: 70 | this.refs.thisNavigator.jumpBack(); 71 | break; 72 | 73 | case NavigatorActionTypes.NAVIGATOR_JUMP_FORWARD: 74 | this.refs.thisNavigator.jumpForward(); 75 | break; 76 | 77 | case NavigatorActionTypes.NAVIGATOR_JUMP_TO: 78 | this.refs.thisNavigator.jumpTo(action); 79 | break; 80 | 81 | case NavigatorActionTypes.NAVIGATOR_PUSH: 82 | this.refs.thisNavigator.push(action); 83 | break; 84 | 85 | case NavigatorActionTypes.NAVIGATOR_POP: 86 | this.refs.thisNavigator.pop(); 87 | break; 88 | 89 | case NavigatorActionTypes.NAVIGATOR_REPLACE: 90 | this.refs.thisNavigator.replace(action); 91 | break; 92 | 93 | case NavigatorActionTypes.NAVIGATOR_REPLACE_AT_INDEX: 94 | this.refs.thisNavigator.replaceAtIndex(action, action.index); 95 | break; 96 | 97 | case NavigatorActionTypes.NAVIGATOR_REPLACE_PREVIOUS: 98 | this.refs.thisNavigator.replacePrevious(action); 99 | break; 100 | 101 | case NavigatorActionTypes.NAVIGATOR_IMMEDIATELY_RESET_ROUTE_STACK: 102 | this.refs.thisNavigator.immediatelyResetRouteStack(action.stack); 103 | break; 104 | 105 | case NavigatorActionTypes.NAVIGATOR_POP_TO_ROUTE: 106 | this.refs.thisNavigator.popToRoute(action); 107 | break; 108 | 109 | case NavigatorActionTypes.NAVIGATOR_POP_TO_TOP: 110 | this.refs.thisNavigator.popToTop(); 111 | break; 112 | 113 | } 114 | 115 | this.props.removeAction(this.props.navigatorKey, action); 116 | }, 117 | 118 | configureScene(route) { 119 | if (!this.props.navigatorActions || !getSceneConfigFrom(route)) { 120 | return null; 121 | } 122 | 123 | return Navigator.SceneConfigs[getSceneConfigFrom(route)]; 124 | }, 125 | 126 | getComponentForKey(key) { 127 | return ComponentMapping[key]; 128 | } 129 | 130 | }); 131 | 132 | export const Component = NavigatorComponent; 133 | 134 | export default connect( 135 | (state, props) => { 136 | return { 137 | navigatorActions: getActionsForNavigatorKey(props.navigatorKey)(state), 138 | initialRoute: getInitialRouteFor(props.navigatorKey)(state) 139 | }; 140 | }, 141 | (dispatch) => { 142 | return bindActionCreators({ removeAction }, dispatch); 143 | } 144 | )(NavigatorComponent); 145 | -------------------------------------------------------------------------------- /js/containers/Todos.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux/native'; 4 | 5 | import Immutable from 'immutable'; 6 | 7 | import { addTodo, deleteTodo, editTodo, completeTodo, completeAll, clearCompleted } from '../actionCreators/TodoActionCreators'; 8 | 9 | import { getTodosFor, getTodos } from '../selectors/TodoSelectors'; 10 | 11 | import { FilterKeys, FilterValues, FilterLabels } from '../constants/TodoFilters'; 12 | import TodoTextInput from '../components/TodoTextInput'; 13 | import TodoList from '../components/TodoList'; 14 | import TodoFilterBar from '../components/TodoFilterBar'; 15 | 16 | const { 17 | StyleSheet, 18 | View, 19 | Text, 20 | TouchableHighlight 21 | } = React; 22 | 23 | const styles = StyleSheet.create({ 24 | container: { 25 | flex: 1, 26 | flexDirection: 'column' 27 | } 28 | }); 29 | 30 | const Todos = React.createClass({ 31 | 32 | propTypes: { 33 | todos: React.PropTypes.instanceOf(Immutable.List).isRequired, 34 | addTodo: React.PropTypes.func.isRequired, 35 | deleteTodo: React.PropTypes.func.isRequired, 36 | editTodo: React.PropTypes.func.isRequired, 37 | completeTodo: React.PropTypes.func.isRequired, 38 | completeAll: React.PropTypes.func.isRequired, 39 | clearCompleted: React.PropTypes.func.isRequired, 40 | }, 41 | 42 | render() { 43 | if (!this.props.todos) { 44 | return ( 45 | null 46 | ); 47 | } 48 | 49 | let todos = getTodosFor(this.state.selectedFilter, this.props.todos); 50 | 51 | return ( 52 | 53 | 54 | 63 | this.onFilterChange(filter)} 67 | /> 68 | 69 | ); 70 | }, 71 | 72 | getInitialState() { 73 | return { 74 | selectedFilter: FilterKeys.SHOW_ALL 75 | }; 76 | }, 77 | 78 | onFilterChange(filter) { 79 | this.setState({ selectedFilter: FilterValues[FilterLabels.indexOf(filter)] }); 80 | } 81 | 82 | }); 83 | 84 | export const Component = Todos; 85 | 86 | export default connect( 87 | (state, props) => { 88 | return { 89 | todos: getTodos(state) 90 | }; 91 | }, 92 | (dispatch) => { 93 | return bindActionCreators({ 94 | addTodo, 95 | deleteTodo, 96 | editTodo, 97 | completeTodo, 98 | completeAll, 99 | clearCompleted 100 | }, dispatch); 101 | } 102 | )(Todos); 103 | -------------------------------------------------------------------------------- /js/middleware/DispatchLogger.js: -------------------------------------------------------------------------------- 1 | import Log from '../util/log'; 2 | 3 | const log = Log('DispatchLogger'); 4 | 5 | export default function DispatchLogger({ dispatch }) { 6 | return (next) => { 7 | return (action) => { 8 | log.debug('Action dispatched: {}', action); 9 | return next(action); 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /js/reducers/NavigationReducer.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | import { REHYDRATE } from 'redux-persist/constants'; 3 | 4 | import NavigationActionTypes from '../constants/NavigationActionTypes'; 5 | import NavigatorKeys from '../constants/NavigatorKeys'; 6 | 7 | const initialState = Immutable.fromJS({ 8 | navigators: { 9 | [NavigatorKeys.ROOT]: { 10 | key: NavigatorKeys.ROOT, 11 | initialRoute: { 12 | id: 0, 13 | componentKey: 'Todos', 14 | sceneConfig: 'FloatFromRight' 15 | }, 16 | actions: [] 17 | } 18 | } 19 | }); 20 | 21 | let appendActionToNavigator = (state, action) => { 22 | return state.updateIn(['navigators', action.navigatorKey, 'actions'], actions => actions.push(Immutable.fromJS(action))); 23 | }; 24 | 25 | export default function(state, action) { 26 | 27 | return initialState; 28 | 29 | switch (action.type) { 30 | 31 | case NavigationActionTypes.NAVIGATOR_JUMP_BACK: 32 | return appendActionToNavigator(state, action); 33 | 34 | case NavigationActionTypes.NAVIGATOR_JUMP_FORWARD: 35 | return appendActionToNavigator(state, action); 36 | 37 | case NavigationActionTypes.NAVIGATOR_JUMP_TO: 38 | return appendActionToNavigator(state, action); 39 | 40 | case NavigationActionTypes.NAVIGATOR_PUSH: 41 | return appendActionToNavigator(state, action); 42 | 43 | case NavigationActionTypes.NAVIGATOR_POP: 44 | return appendActionToNavigator(state, action); 45 | 46 | case NavigationActionTypes.NAVIGATOR_REPLACE: 47 | return appendActionToNavigator(state, action); 48 | 49 | case NavigationActionTypes.NAVIGATOR_REPLACE_AT_INDEX: 50 | return appendActionToNavigator(state, action); 51 | 52 | case NavigationActionTypes.NAVIGATOR_REPLACE_PREVIOUS: 53 | return appendActionToNavigator(state, action); 54 | 55 | case NavigationActionTypes.NAVIGATOR_IMMEDIATELY_RESET_ROUTE_STACK: 56 | return appendActionToNavigator(state, action); 57 | 58 | case NavigationActionTypes.NAVIGATOR_POP_TO_ROUTE: 59 | return appendActionToNavigator(state, action); 60 | 61 | case NavigationActionTypes.NAVIGATOR_POP_TO_TOP: 62 | return appendActionToNavigator(state, action); 63 | 64 | case NavigationActionTypes.NAVIGATOR_REMOVE_ACTION: 65 | return state.updateIn( 66 | ['navigators', action.navigatorKey, 'actions'], 67 | actions => actions.filterNot(a => a == action.action) 68 | ); 69 | 70 | case REHYDRATE: 71 | if (action.key !== 'navigation') { 72 | return state; 73 | } 74 | 75 | state = action.payload; 76 | 77 | return state; 78 | 79 | default: 80 | return state; 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /js/reducers/TodoReducer.js: -------------------------------------------------------------------------------- 1 | import Immutable from 'immutable'; 2 | import { REHYDRATE } from 'redux-persist/constants'; 3 | 4 | import TodoActionTypes from '../constants/TodoActionTypes'; 5 | 6 | const initialState = Immutable.fromJS([ 7 | { 8 | text: 'Use Redux', 9 | completed: false, 10 | id: 0, 11 | }, 12 | ]); 13 | 14 | export default function(state, action) { 15 | 16 | state = state || initialState; 17 | 18 | switch (action.type) { 19 | 20 | case TodoActionTypes.ADD_TODO: 21 | return state.push( 22 | Immutable.Map({ 23 | id: state.reduce((maxId, todo) => Math.max(todo.get('id'), maxId), -1) + 1, 24 | completed: false, 25 | text: action.text 26 | }) 27 | ); 28 | 29 | case TodoActionTypes.DELETE_TODO: 30 | return state.filter(todo => todo.get('id') !== action.id); 31 | 32 | case TodoActionTypes.EDIT_TODO: 33 | return state.map(todo => todo.get('id') === action.id ? todo.set('text', action.text) : todo); 34 | 35 | case TodoActionTypes.COMPLETE_TODO: 36 | return state.map(todo => todo.get('id') === action.id ? todo.set('completed', !todo.get('completed')) : todo); 37 | 38 | case TodoActionTypes.COMPLETE_ALL: 39 | const areAllMarked = state.every(todo => todo.get('completed')); 40 | return state.map(todo => todo.set('completed', areAllMarked)); 41 | 42 | case TodoActionTypes.CLEAR_COMPLETED: 43 | return state.filter(todo => todo.get('completed') === false) 44 | 45 | case REHYDRATE: 46 | if (action.key !== 'todos') { 47 | return state; 48 | } 49 | 50 | state = action.payload; 51 | 52 | return state; 53 | 54 | default: 55 | return state 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /js/reducers/index.js: -------------------------------------------------------------------------------- 1 | import NavigationReducer from './NavigationReducer'; 2 | import TodoReducer from './TodoReducer'; 3 | 4 | export default { 5 | navigation: NavigationReducer, 6 | todos: TodoReducer 7 | }; 8 | -------------------------------------------------------------------------------- /js/selectors/NavigationSelectors.js: -------------------------------------------------------------------------------- 1 | const NavigationSelectors = { 2 | 3 | getNavigatorForKey(key) { 4 | return (state) => { 5 | return state.navigation.getIn(['navigators', key]); 6 | }; 7 | }, 8 | 9 | getActionsForNavigatorKey(key) { 10 | return (state) => { 11 | return state.navigation.getIn(['navigators', key, 'actions']); 12 | } 13 | }, 14 | 15 | getInitialRouteFor(key) { 16 | return (state) => { 17 | return state.navigation.getIn(['navigators', key, 'initialRoute']); 18 | }; 19 | }, 20 | 21 | getSceneConfigFrom(action) { 22 | return action.get('sceneConfig'); 23 | }, 24 | 25 | getTypeFrom(action) { 26 | return action.get('type'); 27 | }, 28 | 29 | getComponentKeyFrom(action) { 30 | return action.get('componentKey'); 31 | }, 32 | 33 | }; 34 | 35 | export default NavigationSelectors; 36 | -------------------------------------------------------------------------------- /js/selectors/TodoSelectors.js: -------------------------------------------------------------------------------- 1 | 2 | import { FilterKeys } from '../constants/TodoFilters'; 3 | 4 | const TodoSelectors = { 5 | 6 | getTodos(state) { 7 | return state.todos; 8 | }, 9 | 10 | getTodosFor(filter, todos) { 11 | if (filter == FilterKeys.SHOW_ACTIVE) { 12 | return todos.filter(todo => !todo.get('completed')); 13 | } 14 | 15 | if (filter == FilterKeys.SHOW_COMPLETED) { 16 | return todos.filter(todo => todo.get('completed')); 17 | } 18 | 19 | return todos; 20 | } 21 | 22 | }; 23 | 24 | export default TodoSelectors; 25 | -------------------------------------------------------------------------------- /js/styles/Color.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import color from 'color'; 3 | 4 | const baseColors = { 5 | cyan: color().cmyk(255, 0, 0, 0), 6 | magenta: color().cmyk(0, 255, 0, 0), 7 | yellow: color().cmyk(0, 0, 255, 0), 8 | black: color().cmyk(0, 0, 0, 255), 9 | red: color().rgb(255, 0, 0), 10 | green: color().rgb(0, 255, 0), 11 | blue: color().rgb(0, 0, 255), 12 | orange: color().hsv(25, 100, 100), 13 | redOrange: color().hsv(12.5, 100, 100), 14 | purple: color().hsv(280, 100, 100), 15 | gray: color().rgb(127, 127, 127), 16 | white: color().rgb(255, 255, 255), 17 | darkslateblue: color('darkslateblue'), 18 | }; 19 | 20 | const fadedColors = _.reduce(baseColors, (dc, c, k) => { 21 | dc[`faded${_.capitalize(k)}`] = c.clone().desaturate(0.5).lighten(0.2); 22 | return dc; 23 | }, {}); 24 | 25 | const darkColors = _.reduce(baseColors, (dc, c, k) => { 26 | dc[`dark${_.capitalize(k)}`] = c.clone().darken(0.5); 27 | return dc; 28 | }, {}); 29 | 30 | const lightColors = _.reduce(baseColors, (dc, c, k) => { 31 | dc[`light${_.capitalize(k)}`] = c.clone().lighten(0.85); 32 | return dc; 33 | }, {}); 34 | 35 | const darkFadedColors = _.reduce(baseColors, (dc, c, k) => { 36 | dc[`darkFaded${_.capitalize(k)}`] = c.clone().darken(0.5).desaturate(0.5); 37 | return dc; 38 | }, {}); 39 | 40 | const lightFadedColors = _.reduce(baseColors, (dc, c, k) => { 41 | dc[`lightFaded${_.capitalize(k)}`] = c.clone().lighten(0.85).desaturate(0.33); 42 | return dc; 43 | }, {}); 44 | 45 | const rawColors = _.extend( 46 | {}, 47 | fadedColors, 48 | baseColors, 49 | darkColors, 50 | lightColors, 51 | darkFadedColors, 52 | lightFadedColors, 53 | ); 54 | 55 | const rgbColors = _.reduce( 56 | rawColors, 57 | (rgbColors, color, key) => { 58 | rgbColors[key] = color.rgbString(); 59 | return rgbColors; 60 | } 61 | , {}); 62 | 63 | const nextColor = (initialColor, phases) => { 64 | let color = initialColor.clone(); 65 | 66 | return (iterations) => { 67 | let newColor = color.clone(); 68 | 69 | for (let i = 0; i < iterations; i++) { 70 | newColor.rotate(360 / phases); 71 | } 72 | 73 | return newColor; 74 | }; 75 | } 76 | 77 | export default { 78 | raw: rawColors, 79 | rgb: rgbColors, 80 | nextColor: nextColor, 81 | } 82 | -------------------------------------------------------------------------------- /js/styles/index.js: -------------------------------------------------------------------------------- 1 | import Color from './Color'; 2 | 3 | export default { 4 | Color 5 | } 6 | -------------------------------------------------------------------------------- /js/util/keyMirror.js: -------------------------------------------------------------------------------- 1 | 2 | import _ from 'lodash'; 3 | 4 | export default function keyMirror(arr) { 5 | if (arr instanceof Array) { 6 | return _.reduce(arr, (result, arrItem) => { 7 | result[arrItem] = arrItem; 8 | return result; 9 | }, {}); 10 | } 11 | 12 | return _.reduce(arr, (result, v, k) => { 13 | result[k] = k; 14 | return result; 15 | }, {}); 16 | } 17 | -------------------------------------------------------------------------------- /js/util/log.js: -------------------------------------------------------------------------------- 1 | 2 | import minilog from 'minilog'; 3 | 4 | minilog.enable(); 5 | 6 | minilog.suggest.clear().deny(/.*/, 'debug'); 7 | 8 | export default function(name) { 9 | return minilog(name || ''); 10 | } 11 | -------------------------------------------------------------------------------- /js/util/mergeById.js: -------------------------------------------------------------------------------- 1 | 2 | import _ from 'lodash'; 3 | 4 | export default function(target, source) { 5 | return _.values(_.reduce(source, (result, sourceVal) => { 6 | if (result[sourceVal.id]) { 7 | result[sourceVal.id] = sourceVal; 8 | } 9 | return result; 10 | }, _.indexBy(target, 'id'))); 11 | } 12 | -------------------------------------------------------------------------------- /js/util/persistenceTransformer.js: -------------------------------------------------------------------------------- 1 | import transit from 'transit-immutable-js'; 2 | import Immutable from 'immutable'; 3 | 4 | export default { 5 | 6 | in(state) { 7 | if (state && typeof state === 'object') { 8 | if (state.toJS) { 9 | return transit.toJSON(state.toJS()); 10 | } 11 | 12 | if (state.toJSON) { 13 | return transit.toJSON(state.toJSON()); 14 | } 15 | 16 | return transit.toJSON(state); 17 | } 18 | 19 | return state; 20 | }, 21 | 22 | out(raw) { 23 | if (typeof raw === 'string') { 24 | return Immutable.fromJS(transit.fromJSON(raw)); 25 | } 26 | 27 | return raw; 28 | } 29 | 30 | }; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeBoilerplate", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-native start", 7 | "test": "./node_modules/.bin/jest", 8 | "test-watch": "./node_modules/.bin/jest --watch" 9 | }, 10 | "dependencies": { 11 | "art": "^0.10.0", 12 | "babel": "^5.8.23", 13 | "babel-core": "^5.8.23", 14 | "bluebird": "^3.0.5", 15 | "color": "^0.10.1", 16 | "eslint": "^1.8.0", 17 | "eslint-plugin-react": "^3.6.3", 18 | "immutable": "^3.7.5", 19 | "invariant": "^2.1.1", 20 | "jest-cli": "^0.7.0", 21 | "klass": "^1.4.1", 22 | "lodash": "^3.10.1", 23 | "minilog": "^2.0.8", 24 | "moment": "^2.10.6", 25 | "react": "^0.14.2", 26 | "react-native": "^0.14.1", 27 | "react-native-swipeout": "^2.0.9", 28 | "react-redux": "^3.1.0", 29 | "react-timer-mixin": "^0.13.3", 30 | "redux": "^3.0.4", 31 | "redux-persist": "^1.0.0", 32 | "redux-persist-immutable": "^1.0.5", 33 | "redux-tcomb": "^0.1.2", 34 | "redux-thunk": "^1.0.0", 35 | "reselect": "^2.0.0", 36 | "testcheck": "^0.1.4", 37 | "transit-immutable-js": "^0.4.0", 38 | "transit-js": "^0.8.837" 39 | }, 40 | "jest": { 41 | "scriptPreprocessor": "jestSupport/scriptPreprocess.js", 42 | "setupEnvScriptFile": "node_modules/react-native/jestSupport/env.js", 43 | "testPathIgnorePatterns": [ 44 | "/node_modules/", 45 | "packager/react-packager/src/Activity/" 46 | ], 47 | "unmockedModulePathPatterns": [ 48 | "node_modules/bluebird", 49 | "node_modules/debug", 50 | "node_modules/immutable", 51 | "node_modules/intl-messageformat", 52 | "node_modules/klass", 53 | "node_modules/lodash", 54 | "node_modules/react", 55 | "node_modules/minilog", 56 | "node_modules/json-stringify-safe", 57 | "invariant", 58 | "js/model", 59 | "js/constants", 60 | "js/util", 61 | "promise", 62 | "source-map" 63 | ], 64 | "moduleFileExtensions": [ 65 | "js", 66 | "json", 67 | "jsx" 68 | ], 69 | "modulePathIgnorePatterns": [ 70 | "newrelic" 71 | ], 72 | "testFileExtensions": [ 73 | "js", 74 | "jsx" 75 | ], 76 | "globals": { 77 | "__DEV__": true 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | 6 | module.exports = { 7 | debug: true, 8 | devtool: 'source-map', 9 | entry: { 10 | 'index.ios': ['./src/main.ios.js'], 11 | 'index.android': ['./src/main.android.js'], 12 | }, 13 | output: { 14 | path: path.resolve(__dirname, 'build'), 15 | filename: '[name].js', 16 | }, 17 | module: { 18 | preLoaders: [ 19 | { 20 | test: /\.(js|jsx|es6)$/, 21 | include: path.resolve(__dirname, 'src'), 22 | loader: "eslint-loader" 23 | } 24 | ], 25 | loaders: [ 26 | { 27 | test: /\.(js|jsx|es6)$/, 28 | exclude: /node_modules/, 29 | loader: 'babel', 30 | query: { 31 | cacheDirectory: true, 32 | presets: ['es2015', 'stage-0', 'react'], 33 | plugins: ['flow-comments'] 34 | } 35 | } 36 | ] 37 | } 38 | }; 39 | --------------------------------------------------------------------------------