├── .gitignore ├── LICENSE ├── README.md ├── __tests__ ├── index.android.js ├── index.ios.js └── infoButtonTest.js ├── android ├── app │ ├── BUCK │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── fonts │ │ │ ├── Andale Mono.ttf │ │ │ ├── Arial Black.ttf │ │ │ ├── Arial.ttf │ │ │ ├── Comic Sans MS.ttf │ │ │ ├── Courier New.ttf │ │ │ ├── Entypo.ttf │ │ │ ├── EvilIcons.ttf │ │ │ ├── FontAwesome.ttf │ │ │ ├── Foundation.ttf │ │ │ ├── Georgia.ttf │ │ │ ├── Ionicons.ttf │ │ │ ├── MaterialCommunityIcons.ttf │ │ │ ├── MaterialIcons.ttf │ │ │ ├── Microsoft Sans Serif.ttf │ │ │ ├── Octicons.ttf │ │ │ ├── Roboto.ttf │ │ │ ├── Roboto_medium.ttf │ │ │ ├── SF-UI-Text-Regular.otf │ │ │ ├── SimpleLineIcons.ttf │ │ │ ├── Skia.ttf │ │ │ ├── Times New Roman.ttf │ │ │ └── Zocial.ttf │ │ ├── java │ │ └── com │ │ │ └── reactnativeeverywhere │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.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 ├── keystores │ ├── BUCK │ └── debug.keystore.properties └── settings.gradle ├── images ├── main.jpeg ├── mic.png ├── sky.jpeg ├── solace.png ├── stopmic.png ├── tutorial-1.png ├── tutorial-2.png └── tutorial-3.png ├── index.android.js ├── index.html ├── index.ios.js ├── index.web.js ├── ios ├── reactNativeEverywhere.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── reactNativeEverywhere.xcscheme ├── reactNativeEverywhere │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@1x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-76x76@3x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ ├── Icon-Small-50x50@1x.png │ │ │ └── Icon-Small-50x50@2x.png │ ├── Info.plist │ └── main.m └── reactNativeEverywhereTests │ ├── Info.plist │ └── reactNativeEverywhereTests.m ├── manifest.json ├── package.json ├── src ├── common │ ├── README.md │ ├── actions │ │ └── README.md │ ├── assets │ │ └── README.md │ ├── components │ │ └── README.md │ ├── reducers │ │ └── README.md │ └── utilities │ │ ├── network │ │ └── README.md │ │ └── storage │ │ ├── README.md │ │ └── store.js ├── images │ ├── info.png │ ├── mic.png │ ├── solace.png │ └── stopmic.png ├── native │ ├── app.native.js │ ├── components │ │ ├── BarGraph.native.js │ │ ├── BarGraphSlides.native.js │ │ ├── Close.native.js │ │ ├── Info.native.js │ │ ├── Legend.native.js │ │ ├── LineGraph.native.js │ │ └── LineGraphSlides.native.js │ ├── customDimensions.js │ ├── reducer │ │ ├── admin.native.js │ │ ├── index.native.js │ │ ├── questions.native.js │ │ ├── quote.native.js │ │ ├── recordings.native.js │ │ └── user.native.js │ ├── screens │ │ ├── Account.native.js │ │ ├── CompleteProfile.native.js │ │ ├── Homepage.native.js │ │ ├── Login.native.js │ │ ├── Picker.native.js │ │ ├── QuestionsModal.native.js │ │ ├── Recording.native.js │ │ ├── Signup.native.js │ │ ├── Tutorial.native.js │ │ └── chartScreens │ │ │ ├── AllTimeAverageChart.native.js │ │ │ ├── AllTimeTotalChart.native.js │ │ │ ├── Charts.native.js │ │ │ ├── IntroToCharts.native.js │ │ │ ├── LatestDataChart.native.js │ │ │ ├── MonthlyAverageChart.native.js │ │ │ ├── MonthlyTotalChart.native.js │ │ │ ├── WeeklyAverageChart.native.js │ │ │ └── WeeklyTotalChart.native.js │ ├── store.native.js │ └── utils │ │ ├── chart.js │ │ ├── dataList.js │ │ └── validation.js └── web │ ├── app.web.js │ └── screens │ └── TopLevelComponent.web.js ├── webpack.config.js └── webpack.config.prod.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/ 3 | # OSX 4 | # 5 | .DS_Store 6 | 7 | # Xcode 8 | # 9 | DerivedData 10 | *.hmap 11 | *.ipa 12 | *.xcuserstate 13 | project.xcworkspace 14 | 15 | # BUCK 16 | buck-out/ 17 | \.buckd/ 18 | android/app/libs 19 | *.keystore 20 | 21 | # fastlane 22 | # 23 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 24 | # screenshots whenever they are needed. 25 | # For more information about the recommended setup visit: 26 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 27 | 28 | fastlane/report.xml 29 | fastlane/Preview.html 30 | fastlane/screenshots 31 | 32 | 33 | ### Xcode ### 34 | # Xcode 35 | # 36 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 37 | 38 | ## Build generated 39 | build/ 40 | DerivedData/ 41 | 42 | ## Various settings 43 | *.pbxuser 44 | !default.pbxuser 45 | *.mode1v3 46 | !default.mode1v3 47 | *.mode2v3 48 | !default.mode2v3 49 | *.perspectivev3 50 | !default.perspectivev3 51 | xcuserdata/ 52 | 53 | ## Other 54 | *.moved-aside 55 | *.xccheckout 56 | *.xcscmblueprint 57 | 58 | 59 | ### Android ### 60 | # Built application files 61 | *.apk 62 | *.ap_ 63 | 64 | # Files for the ART/Dalvik VM 65 | *.dex 66 | 67 | # Java class files 68 | *.class 69 | 70 | # Generated files 71 | bin/ 72 | gen/ 73 | out/ 74 | 75 | # Gradle files 76 | .gradle/ 77 | 78 | # Local configuration file (sdk path, etc) 79 | local.properties 80 | 81 | # Proguard folder generated by Eclipse 82 | proguard/ 83 | 84 | # Log Files 85 | *.log 86 | 87 | # Android Studio Navigation editor temp files 88 | .navigation/ 89 | 90 | # Android Studio captures folder 91 | captures/ 92 | 93 | # Intellij 94 | *.iml 95 | .idea/workspace.xml 96 | .idea/tasks.xml 97 | .idea/libraries 98 | 99 | # Keystore files 100 | *.jks 101 | 102 | # External native build folder generated in Android Studio 2.2 and later 103 | .externalNativeBuild 104 | 105 | ### Android Patch ### 106 | gen-external-apklibs 107 | 108 | 109 | ### Intellij ### 110 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 111 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 112 | 113 | # User-specific stuff: 114 | 115 | # Sensitive or high-churn files: 116 | .idea/dataSources/ 117 | .idea/dataSources.ids 118 | .idea/dataSources.xml 119 | .idea/dataSources.local.xml 120 | .idea/sqlDataSources.xml 121 | .idea/dynamic.xml 122 | .idea/uiDesigner.xml 123 | 124 | # Gradle: 125 | .idea/gradle.xml 126 | 127 | # Mongo Explorer plugin: 128 | .idea/mongoSettings.xml 129 | 130 | ## File-based project format: 131 | *.iws 132 | 133 | ## Plugin-specific files: 134 | 135 | # IntelliJ 136 | /out/ 137 | 138 | # mpeltonen/sbt-idea plugin 139 | .idea_modules/ 140 | 141 | # JIRA plugin 142 | atlassian-ide-plugin.xml 143 | 144 | # Crashlytics plugin (for Android Studio and IntelliJ) 145 | com_crashlytics_export_strings.xml 146 | crashlytics.properties 147 | crashlytics-build.properties 148 | fabric.properties 149 | 150 | ### Intellij Patch ### 151 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 152 | 153 | # *.iml 154 | # modules.xml 155 | # .idea/misc.xml 156 | # *.ipr 157 | 158 | 159 | ### WebStorm ### 160 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 161 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 162 | 163 | # User-specific stuff: 164 | 165 | # Sensitive or high-churn files: 166 | 167 | # Gradle: 168 | 169 | # Mongo Explorer plugin: 170 | 171 | ## File-based project format: 172 | 173 | ## Plugin-specific files: 174 | 175 | # IntelliJ 176 | 177 | # mpeltonen/sbt-idea plugin 178 | 179 | # JIRA plugin 180 | 181 | # Crashlytics plugin (for Android Studio and IntelliJ) 182 | 183 | ### WebStorm Patch ### 184 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 185 | 186 | # *.iml 187 | # modules.xml 188 | # .idea/misc.xml 189 | # *.ipr 190 | 191 | #secrets 192 | secrets.json 193 | 194 | ### Node ### 195 | # Logs 196 | logs 197 | npm-debug.log* 198 | 199 | # Runtime data 200 | pids 201 | *.pid 202 | *.seed 203 | *.pid.lock 204 | 205 | # Directory for instrumented libs generated by jscoverage/JSCover 206 | lib-cov 207 | 208 | # Coverage directory used by tools like istanbul 209 | coverage 210 | 211 | # nyc test coverage 212 | .nyc_output 213 | 214 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 215 | .grunt 216 | 217 | # node-waf configuration 218 | .lock-wscript 219 | 220 | # Compiled binary addons (http://nodejs.org/api/addons.html) 221 | build/Release 222 | 223 | # Dependency directories 224 | node_modules 225 | jspm_packages 226 | 227 | # Optional npm cache directory 228 | .npm 229 | 230 | # Optional eslint cache 231 | .eslintcache 232 | 233 | # Optional REPL history 234 | .node_repl_history 235 | 236 | # Output of 'npm pack' 237 | *.tgz 238 | 239 | # Yarn Integrity file 240 | .yarn-integrity 241 | 242 | 243 | 244 | ### Bower ### 245 | bower_components 246 | .bower-cache 247 | .bower-registry 248 | .bower-tmp 249 | 250 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solace 2 | 3 | Overview Page: http://www.projectsolace.co 4 | 5 | Solace is a mental wellness mobile app that utilizes IBM Watson's Personality/Emotional Insights API to help users observe their own mental and emotional processes over time. Each day, users are encouraged to share their thoughts and feelings with Solace by simply speaking to the app. Solace will then analyze the recordings and output a visual representation of the user's personality and emotional insights. Users will not only have the ability to track their most recent statistics but also be able to check their progress over time. 6 | 7 | The deployed Admin Panel and Backend Server is located at: https://solace-admin.herokuapp.com/ 8 | 9 | To see our test data render for different demographics, you can log in with: 10 | 11 | Email: anuj@anuj.anuj 12 | Password: 123 13 | 14 | The client-side GitHub is located at: https://github.com/jawang12/solace-react-native 15 | 16 | The Chrome extension GitHub is located at: https://github.com/mobiuschang/solace-chrome 17 | 18 | ## Getting Started 19 | 20 | Follow these steps to get the app and backend running on your machine. 21 | 22 | ### Prerequisites 23 | 24 | This guide assumes that you have Node (and npm) and PostgreSQL installed for the backend. 25 | 26 | For the client-side you will need XCode installed. 27 | 28 | If you don't have the prerequisites, you can get them here: 29 | 30 | https://nodejs.org 31 | 32 | https://www.postgresql.org/ 33 | 34 | https://developer.apple.com/xcode/downloads/ 35 | 36 | ### Installing Backend 37 | 38 | ``` 39 | git clone https://github.com/jennyrchan/solace-admin 40 | ``` 41 | 42 | Make sure PostgreSQL is running and in your project directory, run 43 | 44 | ``` 45 | npm install 46 | ``` 47 | 48 | To seed the database 49 | 50 | ``` 51 | npm run seed 52 | ``` 53 | 54 | Then to start the server, run 55 | 56 | ``` 57 | npm start 58 | ``` 59 | 60 | and connect to localhost:1337. 61 | 62 | You can log in with: 63 | 64 | Email: anuj@anuj.anuj 65 | Password: 123 66 | 67 | ### Installing Client-Side 68 | 69 | ``` 70 | git clone https://github.com/jawang12/solace-react-native 71 | ``` 72 | 73 | The application is linked to the deployed server so you do not need a local server running. 74 | 75 | In your project directory, run 76 | 77 | ``` 78 | npm install 79 | ``` 80 | 81 | Then to link the react-native libraries 82 | 83 | ``` 84 | react-native link 85 | ``` 86 | 87 | To start the application 88 | 89 | ``` 90 | react-native run-ios 91 | ``` 92 | 93 | You can log in to the application with: 94 | 95 | Email: anuj@anuj.anuj 96 | Password: 123 97 | 98 | Or you can create your own account and start recording! 99 | 100 | ### Installing Chrome Extension 101 | 102 | ``` 103 | git clone https://github.com/mobiuschang/solace-chrome 104 | ``` 105 | 106 | In your Chrome browser, go to: 107 | 108 | ``` 109 | chrome://extensions/ 110 | ``` 111 | 112 | Check the box labeled *Developer mode* and click *Load unpacked extension...* 113 | 114 | Then select the project directory, and the extension will automatically load! 115 | 116 | ## Running the tests 117 | 118 | Our test suite features testing for the routing, database, API, and frontend. 119 | 120 | On the backend we test Express, our database models, and our Watson API behavior. 121 | 122 | On the frontend, we test our React Native components and Redux store for expected behavior, as well as the specific actions of our libraries and modules. 123 | 124 | All tests are run via 125 | 126 | ``` 127 | npm test 128 | ``` 129 | 130 | ## Authors 131 | 132 | * **Anuj Shah** - [GitHub](https://github.com/anujshah108) 133 | * **Jenny Chan** - [GitHub](https://github.com/jennyrchan) 134 | * **Winston Wang** - [GitHub](https://github.com/mobiuschang) 135 | * **Jimmy Wang** - [GitHub](https://github.com/jawang12) 136 | -------------------------------------------------------------------------------- /__tests__/index.android.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.android.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /__tests__/index.ios.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.ios.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /__tests__/infoButtonTest.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import InfoButton from '../src/native/components/Info.native'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | test('renders correctly', () => { 9 | const infoButton = renderer.create( 10 | 11 | ) 12 | let tree = infoButton.toJSON(); 13 | expect(tree).toMatchSnapshot(); 14 | }); 15 | -------------------------------------------------------------------------------- /android/app/BUCK: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # To learn about Buck see [Docs](https://buckbuild.com/). 4 | # To run your application with Buck: 5 | # - install Buck 6 | # - `npm start` - to start the packager 7 | # - `cd android` 8 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 9 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 10 | # - `buck install -r android/app` - compile, install and run application 11 | # 12 | 13 | lib_deps = [] 14 | for jarfile in glob(['libs/*.jar']): 15 | name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile) 16 | lib_deps.append(':' + name) 17 | prebuilt_jar( 18 | name = name, 19 | binary_jar = jarfile, 20 | ) 21 | 22 | for aarfile in glob(['libs/*.aar']): 23 | name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile) 24 | lib_deps.append(':' + name) 25 | android_prebuilt_aar( 26 | name = name, 27 | aar = aarfile, 28 | ) 29 | 30 | android_library( 31 | name = 'all-libs', 32 | exported_deps = lib_deps 33 | ) 34 | 35 | android_library( 36 | name = 'app-code', 37 | srcs = glob([ 38 | 'src/main/java/**/*.java', 39 | ]), 40 | deps = [ 41 | ':all-libs', 42 | ':build_config', 43 | ':res', 44 | ], 45 | ) 46 | 47 | android_build_config( 48 | name = 'build_config', 49 | package = 'com.reactnativeeverywhere', 50 | ) 51 | 52 | android_resource( 53 | name = 'res', 54 | res = 'src/main/res', 55 | package = 'com.reactnativeeverywhere', 56 | ) 57 | 58 | android_binary( 59 | name = 'app', 60 | package_type = 'debug', 61 | manifest = 'src/main/AndroidManifest.xml', 62 | keystore = '//android/keystores:debug', 63 | deps = [ 64 | ':app-code', 65 | ], 66 | ) 67 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // whether to bundle JS and assets in debug mode 22 | * bundleInDebug: false, 23 | * 24 | * // whether to bundle JS and assets in release mode 25 | * bundleInRelease: true, 26 | * 27 | * // whether to bundle JS and assets in another build variant (if configured). 28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 29 | * // The configuration property can be in the following formats 30 | * // 'bundleIn${productFlavor}${buildType}' 31 | * // 'bundleIn${buildType}' 32 | * // bundleInFreeDebug: true, 33 | * // bundleInPaidRelease: true, 34 | * // bundleInBeta: true, 35 | * 36 | * // the root of your project, i.e. where "package.json" lives 37 | * root: "../../", 38 | * 39 | * // where to put the JS bundle asset in debug mode 40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 41 | * 42 | * // where to put the JS bundle asset in release mode 43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 44 | * 45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 46 | * // require('./image.png')), in debug mode 47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 48 | * 49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 50 | * // require('./image.png')), in release mode 51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 52 | * 53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 57 | * // for example, you might want to remove it from here. 58 | * inputExcludes: ["android/**", "ios/**"], 59 | * 60 | * // override which node gets called and with what additional arguments 61 | * nodeExecutableAndArgs: ["node"] 62 | * 63 | * // supply additional arguments to the packager 64 | * extraPackagerArgs: [] 65 | * ] 66 | */ 67 | 68 | apply from: "../../node_modules/react-native/react.gradle" 69 | 70 | /** 71 | * Set this to true to create two separate APKs instead of one: 72 | * - An APK that only works on ARM devices 73 | * - An APK that only works on x86 devices 74 | * The advantage is the size of the APK is reduced by about 4MB. 75 | * Upload all the APKs to the Play Store and people will download 76 | * the correct one based on the CPU architecture of their device. 77 | */ 78 | def enableSeparateBuildPerCPUArchitecture = false 79 | 80 | /** 81 | * Run Proguard to shrink the Java bytecode in release builds. 82 | */ 83 | def enableProguardInReleaseBuilds = false 84 | 85 | android { 86 | compileSdkVersion 23 87 | buildToolsVersion "23.0.1" 88 | 89 | defaultConfig { 90 | applicationId "com.reactnativeeverywhere" 91 | minSdkVersion 16 92 | targetSdkVersion 22 93 | versionCode 1 94 | versionName "1.0" 95 | ndk { 96 | abiFilters "armeabi-v7a", "x86" 97 | } 98 | } 99 | splits { 100 | abi { 101 | reset() 102 | enable enableSeparateBuildPerCPUArchitecture 103 | universalApk false // If true, also generate a universal APK 104 | include "armeabi-v7a", "x86" 105 | } 106 | } 107 | buildTypes { 108 | release { 109 | minifyEnabled enableProguardInReleaseBuilds 110 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 111 | } 112 | } 113 | // applicationVariants are e.g. debug, release 114 | applicationVariants.all { variant -> 115 | variant.outputs.each { output -> 116 | // For each separate APK per architecture, set a unique version code as described here: 117 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 118 | def versionCodes = ["armeabi-v7a":1, "x86":2] 119 | def abi = output.getFilter(OutputFile.ABI) 120 | if (abi != null) { // null for the universal-debug, universal-release variants 121 | output.versionCodeOverride = 122 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 123 | } 124 | } 125 | } 126 | } 127 | 128 | dependencies { 129 | compile project(':react-native-linear-gradient') 130 | compile project(':react-native-spinkit') 131 | compile project(':react-native-svg') 132 | compile project(':react-native-audio') 133 | compile project(':react-native-blur') 134 | compile project(':react-native-vector-icons') 135 | compile fileTree(dir: "libs", include: ["*.jar"]) 136 | compile "com.android.support:appcompat-v7:23.0.1" 137 | compile "com.facebook.react:react-native:+" // From node_modules 138 | } 139 | 140 | // Run this once to be able to run the application with BUCK 141 | // puts all compile dependencies into folder libs for BUCK to use 142 | task copyDownloadableDepsToLibs(type: Copy) { 143 | from configurations.compile 144 | into 'libs' 145 | } 146 | -------------------------------------------------------------------------------- /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 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # okhttp 54 | 55 | -keepattributes Signature 56 | -keepattributes *Annotation* 57 | -keep class okhttp3.** { *; } 58 | -keep interface okhttp3.** { *; } 59 | -dontwarn okhttp3.** 60 | 61 | # okio 62 | 63 | -keep class sun.misc.Unsafe { *; } 64 | -dontwarn java.nio.file.* 65 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 66 | -dontwarn okio.** 67 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Andale Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Andale Mono.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Arial Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Arial Black.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Arial.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Comic Sans MS.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Comic Sans MS.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Courier New.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Courier New.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Georgia.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Georgia.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Microsoft Sans Serif.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Microsoft Sans Serif.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Roboto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Roboto.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Roboto_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Roboto_medium.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SF-UI-Text-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/SF-UI-Text-Regular.otf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Skia.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Skia.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Times New Roman.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Times New Roman.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /android/app/src/main/java/com/reactnativeeverywhere/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeeverywhere; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "reactNativeEverywhere"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/reactnativeeverywhere/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeeverywhere; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | import com.facebook.react.ReactApplication; 7 | import com.BV.LinearGradient.LinearGradientPackage; 8 | import com.react.rnspinkit.RNSpinkitPackage; 9 | import com.horcrux.svg.SvgPackage; 10 | import com.rnim.rn.audio.ReactNativeAudioPackage; 11 | import com.cmcewen.blurview.BlurViewPackage; 12 | import com.oblador.vectoricons.VectorIconsPackage; 13 | import com.facebook.react.ReactInstanceManager; 14 | import com.facebook.react.ReactNativeHost; 15 | import com.facebook.react.ReactPackage; 16 | import com.facebook.react.shell.MainReactPackage; 17 | import com.facebook.soloader.SoLoader; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | public class MainApplication extends Application implements ReactApplication { 23 | 24 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 25 | @Override 26 | protected boolean getUseDeveloperSupport() { 27 | return BuildConfig.DEBUG; 28 | } 29 | 30 | @Override 31 | protected List getPackages() { 32 | return Arrays.asList( 33 | new MainReactPackage(), 34 | new LinearGradientPackage(), 35 | new RNSpinkitPackage(), 36 | <<<<<<< HEAD 37 | ======= 38 | new LinearGradientPackage(), 39 | >>>>>>> master 40 | new RNSpinkitPackage(), 41 | new SvgPackage(), 42 | new ReactNativeAudioPackage(), 43 | new BlurViewPackage(), 44 | new VectorIconsPackage() 45 | ); 46 | } 47 | }; 48 | 49 | @Override 50 | public ReactNativeHost getReactNativeHost() { 51 | return mReactNativeHost; 52 | } 53 | 54 | @Override 55 | public void onCreate() { 56 | super.onCreate(); 57 | SoLoader.init(this, /* native exopackage */ false); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | reactNativeEverywhere 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 | // Add jitpack repository (added by react-native-spinkit) 18 | maven { url "https://jitpack.io" } 19 | mavenLocal() 20 | jcenter() 21 | maven { 22 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 23 | url "$rootDir/../node_modules/react-native/android" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /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/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/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/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = 'debug', 3 | store = 'debug.keystore', 4 | properties = 'debug.keystore.properties', 5 | visibility = [ 6 | 'PUBLIC', 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'reactNativeEverywhere' 2 | include ':react-native-linear-gradient' 3 | project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android') 4 | include ':react-native-spinkit' 5 | project(':react-native-spinkit').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-spinkit/android') 6 | include ':react-native-spinkit' 7 | project(':react-native-spinkit').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-spinkit/android') 8 | include ':react-native-svg' 9 | project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android') 10 | include ':react-native-audio' 11 | project(':react-native-audio').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-audio/android') 12 | include ':react-native-blur' 13 | project(':react-native-blur').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-blur/android') 14 | include ':react-native-vector-icons' 15 | project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') 16 | 17 | include ':app' 18 | -------------------------------------------------------------------------------- /images/main.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/main.jpeg -------------------------------------------------------------------------------- /images/mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/mic.png -------------------------------------------------------------------------------- /images/sky.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/sky.jpeg -------------------------------------------------------------------------------- /images/solace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/solace.png -------------------------------------------------------------------------------- /images/stopmic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/stopmic.png -------------------------------------------------------------------------------- /images/tutorial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/tutorial-1.png -------------------------------------------------------------------------------- /images/tutorial-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/tutorial-2.png -------------------------------------------------------------------------------- /images/tutorial-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/images/tutorial-3.png -------------------------------------------------------------------------------- /index.android.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | AppRegistry, 4 | } from 'react-native'; 5 | import App from './src/native/app.native' 6 | 7 | export default class reactNativeEverywhere extends Component { 8 | render() { 9 | return ( 10 | 11 | ); 12 | } 13 | } 14 | 15 | AppRegistry.registerComponent('reactNativeEverywhere', () => reactNativeEverywhere); 16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | React Native Everywhere 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { AppRegistry } from 'react-native'; 3 | import App from './src/native/app.native' 4 | 5 | export default class reactNativeEverywhere extends Component { 6 | render() { 7 | return ( 8 | 9 | ); 10 | } 11 | } 12 | 13 | AppRegistry.registerComponent('reactNativeEverywhere', () => reactNativeEverywhere); 14 | -------------------------------------------------------------------------------- /index.web.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import App from './src/web/app.web' 3 | import ReactNative from 'react-native' 4 | 5 | ReactNative.render(, document.getElementById('react-native-everywhere')); -------------------------------------------------------------------------------- /ios/reactNativeEverywhere.xcodeproj/xcshareddata/xcschemes/reactNativeEverywhere.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/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/reactNativeEverywhere/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 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | NSURL *jsCodeLocation; 20 | 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | 23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 24 | moduleName:@"reactNativeEverywhere" 25 | initialProperties:nil 26 | launchOptions:launchOptions]; 27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | UIViewController *rootViewController = [UIViewController new]; 31 | rootViewController.view = rootView; 32 | self.window.rootViewController = rootViewController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/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/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images":[ 3 | { 4 | "idiom":"iphone", 5 | "size":"20x20", 6 | "scale":"2x", 7 | "filename":"Icon-App-20x20@2x.png" 8 | }, 9 | { 10 | "idiom":"iphone", 11 | "size":"20x20", 12 | "scale":"3x", 13 | "filename":"Icon-App-20x20@3x.png" 14 | }, 15 | { 16 | "idiom":"iphone", 17 | "size":"29x29", 18 | "scale":"1x", 19 | "filename":"Icon-App-29x29@1x.png" 20 | }, 21 | { 22 | "idiom":"iphone", 23 | "size":"29x29", 24 | "scale":"2x", 25 | "filename":"Icon-App-29x29@2x.png" 26 | }, 27 | { 28 | "idiom":"iphone", 29 | "size":"29x29", 30 | "scale":"3x", 31 | "filename":"Icon-App-29x29@3x.png" 32 | }, 33 | { 34 | "idiom":"iphone", 35 | "size":"40x40", 36 | "scale":"1x", 37 | "filename":"Icon-App-40x40@1x.png" 38 | }, 39 | { 40 | "idiom":"iphone", 41 | "size":"40x40", 42 | "scale":"2x", 43 | "filename":"Icon-App-40x40@2x.png" 44 | }, 45 | { 46 | "idiom":"iphone", 47 | "size":"40x40", 48 | "scale":"3x", 49 | "filename":"Icon-App-40x40@3x.png" 50 | }, 51 | { 52 | "idiom":"iphone", 53 | "size":"57x57", 54 | "scale":"1x", 55 | "filename":"Icon-App-57x57@1x.png" 56 | }, 57 | { 58 | "idiom":"iphone", 59 | "size":"57x57", 60 | "scale":"2x", 61 | "filename":"Icon-App-57x57@2x.png" 62 | }, 63 | { 64 | "idiom":"iphone", 65 | "size":"60x60", 66 | "scale":"1x", 67 | "filename":"Icon-App-60x60@1x.png" 68 | }, 69 | { 70 | "idiom":"iphone", 71 | "size":"60x60", 72 | "scale":"2x", 73 | "filename":"Icon-App-60x60@2x.png" 74 | }, 75 | { 76 | "idiom":"iphone", 77 | "size":"60x60", 78 | "scale":"3x", 79 | "filename":"Icon-App-60x60@3x.png" 80 | }, 81 | { 82 | "idiom":"iphone", 83 | "size":"76x76", 84 | "scale":"1x", 85 | "filename":"Icon-App-76x76@1x.png" 86 | }, 87 | { 88 | "idiom":"ipad", 89 | "size":"20x20", 90 | "scale":"1x", 91 | "filename":"Icon-App-20x20@1x.png" 92 | }, 93 | { 94 | "idiom":"ipad", 95 | "size":"20x20", 96 | "scale":"2x", 97 | "filename":"Icon-App-20x20@2x.png" 98 | }, 99 | { 100 | "idiom":"ipad", 101 | "size":"29x29", 102 | "scale":"1x", 103 | "filename":"Icon-App-29x29@1x.png" 104 | }, 105 | { 106 | "idiom":"ipad", 107 | "size":"29x29", 108 | "scale":"2x", 109 | "filename":"Icon-App-29x29@2x.png" 110 | }, 111 | { 112 | "idiom":"ipad", 113 | "size":"40x40", 114 | "scale":"1x", 115 | "filename":"Icon-App-40x40@1x.png" 116 | }, 117 | { 118 | "idiom":"ipad", 119 | "size":"40x40", 120 | "scale":"2x", 121 | "filename":"Icon-App-40x40@2x.png" 122 | }, 123 | { 124 | "size" : "50x50", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-Small-50x50@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "50x50", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-Small-50x50@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "idiom":"ipad", 137 | "size":"72x72", 138 | "scale":"1x", 139 | "filename":"Icon-App-72x72@1x.png" 140 | }, 141 | { 142 | "idiom":"ipad", 143 | "size":"72x72", 144 | "scale":"2x", 145 | "filename":"Icon-App-72x72@2x.png" 146 | }, 147 | { 148 | "idiom":"ipad", 149 | "size":"76x76", 150 | "scale":"1x", 151 | "filename":"Icon-App-76x76@1x.png" 152 | }, 153 | { 154 | "idiom":"ipad", 155 | "size":"76x76", 156 | "scale":"2x", 157 | "filename":"Icon-App-76x76@2x.png" 158 | }, 159 | { 160 | "idiom":"ipad", 161 | "size":"76x76", 162 | "scale":"3x", 163 | "filename":"Icon-App-76x76@3x.png" 164 | }, 165 | { 166 | "idiom":"ipad", 167 | "size":"83.5x83.5", 168 | "scale":"2x", 169 | "filename":"Icon-App-83.5x83.5@2x.png" 170 | } 171 | ], 172 | "info":{ 173 | "version":1, 174 | "author":"makeappicon" 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@3x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/ios/reactNativeEverywhere/Images.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Solace 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | NSMicrophoneUsageDescription 41 | This sample uses the microphone to record your speech and convert it to text. 42 | UIAppFonts 43 | 44 | Entypo.ttf 45 | EvilIcons.ttf 46 | FontAwesome.ttf 47 | Foundation.ttf 48 | Ionicons.ttf 49 | MaterialCommunityIcons.ttf 50 | MaterialIcons.ttf 51 | Octicons.ttf 52 | SimpleLineIcons.ttf 53 | Zocial.ttf 54 | Andale Mono.ttf 55 | Arial Black.ttf 56 | Arial.ttf 57 | Comic Sans MS.ttf 58 | Courier New.ttf 59 | Georgia.ttf 60 | Microsoft Sans Serif.ttf 61 | Roboto_medium.ttf 62 | Roboto.ttf 63 | SF-UI-Text-Regular.otf 64 | Skia.ttf 65 | Times New Roman.ttf 66 | 67 | UILaunchStoryboardName 68 | LaunchScreen 69 | UIRequiredDeviceCapabilities 70 | 71 | armv7 72 | 73 | UISupportedInterfaceOrientations 74 | 75 | UIInterfaceOrientationPortrait 76 | UIInterfaceOrientationLandscapeLeft 77 | UIInterfaceOrientationLandscapeRight 78 | 79 | UIViewControllerBasedStatusBarAppearance 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /ios/reactNativeEverywhere/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/reactNativeEverywhereTests/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/reactNativeEverywhereTests/reactNativeEverywhereTests.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 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface reactNativeEverywhereTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation reactNativeEverywhereTests 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, RCTLogSource source, 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 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React-Native-Everywhere", 3 | "short_name": "RNE", 4 | "icons": [ 5 | { 6 | "src": "", 7 | "sizes": "72x72 96x96 128x128 256x256" 8 | } 9 | ], 10 | "start_url": "/", 11 | "background_color": "#FFFFFF", 12 | "display": "fullscreen", 13 | "orientation": "portrait", 14 | "theme_color": "#018CCF" 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solace-react-native", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest", 8 | "web": "./node_modules/.bin/webpack-dev-server --inline", 9 | "build": "babel-node tools/build.js" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.15.3", 13 | "file-loader": "^0.9.0", 14 | "native-base": "^0.5.22", 15 | "react": "^15.4.2", 16 | "react-dom": "^15.3.2", 17 | "react-native": "0.38.0", 18 | "react-native-audio": "^3.2.0", 19 | "react-native-aws3": "0.0.3", 20 | "react-native-blur": "^2.0.0", 21 | "react-native-button-component": "^0.1.9", 22 | "react-native-easy-grid": "^0.1.8", 23 | "react-native-floating-label-text-input": "^0.1.2", 24 | "react-native-keyboard-aware-scroll-view": "^0.2.7", 25 | "react-native-router-flux": "^3.37.0", 26 | "react-native-spinkit": "^0.1.5", 27 | "react-native-svg": "^4.1.0", 28 | "react-native-swiper": "^1.5.4", 29 | "react-native-vector-icons": "^4.0.0", 30 | "react-native-web": "0.0.65", 31 | "react-redux": "^5.0.2", 32 | "react-router": "^3.0.0", 33 | "redux": "^3.6.0", 34 | "redux-logger": "^2.7.4", 35 | "redux-thunk": "^2.2.0", 36 | "tcomb-form-native": "^0.6.4", 37 | "victory-native": "^0.6.0" 38 | }, 39 | "devDependencies": { 40 | "babel-jest": "18.0.0", 41 | "babel-loader": "^6.2.10", 42 | "babel-polyfill": "^6.20.0", 43 | "babel-runtime": "^6.20.0", 44 | "url-loader": "^0.5.7", 45 | "babel-plugin-transform-runtime": "^6.15.0", 46 | "babel-preset-es2015": "^6.18.0", 47 | "babel-preset-react": "^6.16.0", 48 | "babel-preset-react-native": "1.9.1", 49 | "babel-preset-stage-0": "^6.16.0", 50 | "jest": "18.0.0", 51 | "react-test-renderer": "15.3.1", 52 | "webpack": "^1.14.0", 53 | "webpack-dev-server": "^1.16.2" 54 | }, 55 | "jest": { 56 | "preset": "react-native" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/common/README.md: -------------------------------------------------------------------------------- 1 | ###Actions 2 | ###Assets 3 | ###Components 4 | ###Reducers 5 | ###Utilities -------------------------------------------------------------------------------- /src/common/actions/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/actions/README.md -------------------------------------------------------------------------------- /src/common/assets/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/assets/README.md -------------------------------------------------------------------------------- /src/common/components/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/components/README.md -------------------------------------------------------------------------------- /src/common/reducers/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/reducers/README.md -------------------------------------------------------------------------------- /src/common/utilities/network/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/utilities/network/README.md -------------------------------------------------------------------------------- /src/common/utilities/storage/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/utilities/storage/README.md -------------------------------------------------------------------------------- /src/common/utilities/storage/store.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/common/utilities/storage/store.js -------------------------------------------------------------------------------- /src/images/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/images/info.png -------------------------------------------------------------------------------- /src/images/mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/images/mic.png -------------------------------------------------------------------------------- /src/images/solace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/images/solace.png -------------------------------------------------------------------------------- /src/images/stopmic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/images/stopmic.png -------------------------------------------------------------------------------- /src/native/app.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Platform, Image } from 'react-native'; 3 | import {Scene, Router} from 'react-native-router-flux'; 4 | import { Provider } from 'react-redux'; 5 | import store from './store.native'; 6 | 7 | import Login from './screens/Login.native'; 8 | import Signup from './screens/Signup.native'; 9 | import Homepage from './screens/Homepage.native'; 10 | import QuestionsModal from './screens/QuestionsModal.native'; 11 | import CompleteProfile from './screens/CompleteProfile.native'; 12 | import Tutorial from './screens/Tutorial.native'; 13 | 14 | // Charts data 15 | import Charts from './screens/chartScreens/Charts.native'; 16 | import IntroToCharts from './screens/chartScreens/IntroToCharts.native'; 17 | import LatestDataChart from './screens/chartScreens/LatestDataChart.native'; 18 | import WeeklyAverageChart from './screens/chartScreens/WeeklyAverageChart.native'; 19 | import MonthlyAverageChart from './screens/chartScreens/MonthlyAverageChart.native'; 20 | import AllTimeAverageChart from './screens/chartScreens/AllTimeAverageChart.native'; 21 | import WeeklyTotalChart from './screens/chartScreens/WeeklyTotalChart.native'; 22 | import MonthlyTotalChart from './screens/chartScreens/MonthlyTotalChart.native'; 23 | import AllTimeTotalChart from './screens/chartScreens/AllTimeTotalChart.native'; 24 | import customDimensions from './customDimensions'; 25 | 26 | export default class App extends React.Component { 27 | 28 | render() { 29 | return ( 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/native/components/BarGraph.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import { VictoryChart, VictoryBar, VictoryTheme, VictoryLabel, VictoryAxis } from 'victory-native'; 4 | import { colorArray } from '../utils/chart'; 5 | 6 | 7 | export default BarGraph = ({data, labels, range, axisLength}) => { //data and labels are arrays of objects 8 | 9 | const dataRange = (type, numRange) => { 10 | numRange = numRange.split('-'); 11 | return type.slice(+numRange[0], +numRange[1]); 12 | }; 13 | 14 | return ( 15 | 16 | 32 | colorArray[data.x - 1] 46 | } 47 | }} 48 | data={range ? dataRange(data, range) : data} 49 | /> 50 | 51 | ) 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/native/components/BarGraphSlides.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Text, ScrollView } from 'react-native'; 3 | import Swiper from 'react-native-swiper'; 4 | import { personality, tone, barDomainCoords, barGraphTitles, personalityDataRange } from '../utils/chart'; 5 | import BarGraph from './BarGraph.native'; 6 | import InfoButton from './Info.native'; 7 | import CloseButton from './Close.native'; 8 | import { personalityTitles, toneTitles } from '../utils/chart'; 9 | 10 | 11 | export default BarGraphSlides = ({personalityData, personalityLabels, toneData, toneLabels}) => { 12 | 13 | const generateSlides = () => { 14 | const output = []; 15 | for (let i = 0; i <= 4; i++) { 16 | let data = personalityData; 17 | let labels = personalityLabels; 18 | if (i === 4) { 19 | data = toneData; 20 | labels = toneLabels; 21 | } 22 | output.push( 23 | 24 | 25 | 26 | {barGraphTitles[i]} 27 | 28 | 29 | 30 | 31 | ) 32 | } return output; 33 | }; 34 | 35 | return ( 36 | 37 | { generateSlides() } 38 | 39 | ); 40 | } 41 | 42 | const styles = StyleSheet.create({ 43 | slide: { 44 | flex: 1, 45 | justifyContent: 'center', 46 | alignItems: 'center' 47 | }, 48 | title: { 49 | color: 'white', 50 | fontSize: 20, 51 | fontWeight: 'bold', 52 | shadowColor: '#000000', 53 | shadowOffset: { 54 | height: 1 55 | }, 56 | shadowRadius: 2, 57 | shadowOpacity: 0.5 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /src/native/components/Close.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, TouchableOpacity } from 'react-native'; 3 | import { Icon } from 'native-base'; 4 | import { Actions } from 'react-native-router-flux'; 5 | 6 | export default CloseButton = () => { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/native/components/Info.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, TouchableOpacity, Alert } from 'react-native'; 3 | import { Icon } from 'native-base'; 4 | 5 | export default InfoButton = (props) => { 6 | return ( 7 | Alert.alert( 10 | '', 11 | props.info 12 | )}> 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/native/components/Legend.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import { colorArray } from '../utils/chart'; 4 | 5 | export default Legend = ({start, end, type}) => { 6 | function descriptions() { 7 | var output = []; 8 | for (var i = start; i <= end; i++) { 9 | output.push( 10 | 11 | 12 | {type[i].key} 13 | 14 | ) 15 | } return output; 16 | } 17 | return ( 18 | 19 | {descriptions()} 20 | 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /src/native/components/LineGraph.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import { VictoryChart, VictoryLine, VictoryTheme, VictoryLabel, VictoryAxis } from 'victory-native'; 4 | import { colorArray } from '../utils/chart'; 5 | 6 | 7 | export default LineGraph = ({start, end, type, xAxisLength}) => { 8 | 9 | const graphLines = (typeOfTraitArray, color = colorArray) => { 10 | const output = []; 11 | for (let i = start; i <= end; i++) { 12 | output.push( 13 | datum.score * 100} 19 | style={{ 20 | data: {stroke: color[i]}, 21 | labels: {fontSize: 12, fill: 'white'} 22 | }} 23 | labelComponent={} 24 | /> 25 | ) 26 | } return output; 27 | }; 28 | 29 | return ( 30 | 31 | 45 | 59 | { graphLines(type) } 60 | 61 | ) 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/native/components/LineGraphSlides.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Text, ScrollView } from 'react-native'; 3 | import Swiper from 'react-native-swiper'; 4 | import { personality, emotional, language, social } from '../utils/chart'; 5 | import Legend from './Legend.native'; 6 | import LineGraph from './LineGraph.native'; 7 | import InfoButton from './Info.native'; 8 | import CloseButton from './Close.native'; 9 | import { personalityTitles, toneTitles } from '../utils/chart'; 10 | 11 | export default Graphs = ({personalityArray, toneArray, xAxisLength}) => { 12 | //type an array of objects thats either the personality or tone; titles is an array of graph titles; 13 | const personalityGraph = () => { 14 | const output = []; 15 | let count = 0; 16 | for (let i = 0; i <= 14; i += 3) { // 0-14 represents the amount of personality traits that are represented 17 | output.push( 18 | 19 | 20 | 21 | { personalityTitles[count] } 22 | 23 | 24 | 25 | 26 | 27 | ) 28 | count++; 29 | } return output; 30 | } 31 | 32 | const toneGraph = (trait = emotional) => { 33 | const output = []; 34 | let count = 0; 35 | for (let i = 0; i <= 12; i += 3) { 36 | let endPoint = i + 2; 37 | if (count === 2) trait = language; 38 | if (count > 2) trait = social; 39 | if (count === 1 || count === 4) endPoint = i + 1; // this condition deals with graphs that have only 2 comparisons 40 | output.push( 41 | 42 | 43 | 44 | { toneTitles[count] } 45 | 46 | 47 | 48 | 49 | 50 | ) 51 | if (count === 1 || count === 4) i -= 1; 52 | count++; 53 | } return output; 54 | } 55 | 56 | const slides = personalityGraph().concat(toneGraph()); 57 | 58 | return ( 59 | 60 | { slides } 61 | 62 | ) 63 | } 64 | 65 | const styles = StyleSheet.create({ 66 | slide: { 67 | flex: 1, 68 | justifyContent: 'center', 69 | alignItems: 'center' 70 | }, 71 | title: { 72 | color: 'white', 73 | fontSize: 20, 74 | fontWeight: 'bold', 75 | shadowColor: '#000000', 76 | shadowOffset: { 77 | height: 1 78 | }, 79 | shadowRadius: 2, 80 | shadowOpacity: 0.5 81 | } 82 | }); 83 | -------------------------------------------------------------------------------- /src/native/customDimensions.js: -------------------------------------------------------------------------------- 1 | import { Dimensions, NavigationExperimental } from 'react-native'; 2 | import { Actions } from 'react-native-router-flux'; 3 | 4 | const screenSize = Dimensions.get('window'); 5 | 6 | const { 7 | Card: { 8 | CardStackPanResponder: NavigationCardStackPanResponder 9 | } 10 | } = NavigationExperimental; 11 | 12 | const { 13 | Directions: { 14 | HORIZONTAL 15 | } 16 | } = NavigationCardStackPanResponder; 17 | 18 | const customDimensions = (props) => { 19 | let { scene } = props; 20 | 21 | let direction = (scene.navigationState != null && scene.navigationState.direction != null) 22 | ? scene.navigationState.direction 23 | : HORIZONTAL; 24 | 25 | // By default, onNavigateBack() should be pop() 26 | // but we'll try to obtain current scene's custom onBack method 27 | let onNavigateBack = (scene.navigationState != null && scene.navigationState.onBack != null) 28 | ? scene.navigationState.onBack 29 | : Actions.pop; 30 | 31 | // Enlarge gesture response distance 32 | let gestureResponseDistance = direction == HORIZONTAL 33 | ? screenSize.width * 0.8 34 | : screenSize.height * 0.5; 35 | 36 | let customProps = Object.assign({}, props, { gestureResponseDistance, onNavigateBack }); 37 | return direction == HORIZONTAL 38 | ? NavigationCardStackPanResponder.forHorizontal(customProps) 39 | : NavigationCardStackPanResponder.forVertical(customProps); 40 | }; 41 | 42 | export default customDimensions; 43 | -------------------------------------------------------------------------------- /src/native/reducer/admin.native.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | /* ----------------- ACTIONS ------------------ */ 4 | 5 | const RECEIVE_RELIGION_DATA = 'RECEIVE_RELIGION_DATA'; 6 | const RECEIVE_OCCUPATION_DATA = 'RECEIVE_OCCUPATION_DATA'; 7 | const RECEIVE_INCOME_DATA = 'RECEIVE_INCOME_DATA'; 8 | const RECEIVE_ETHNICITY_DATA = 'RECEIVE_ETHNICITY_DATA'; 9 | const RECEIVE_EDUCATION_DATA = 'RECEIVE_EDUCATION_DATA'; 10 | const RECEIVE_MARITAL_DATA = 'RECEIVE_MARITAL_DATA'; 11 | const RECEIVE_ZIP_CODE_DATA = 'RECEIVE_ZIP_CODE_DATA'; 12 | const RECEIVE_GENDER_DATA = 'RECEIVE_GENDER_DATA'; 13 | const GET_IMAGE = 'GET_IMAGE' 14 | 15 | /* ----------------- ACTION CREATORS ------------------ */ 16 | 17 | export const getImageId = (imageId) => { 18 | return { 19 | type: GET_IMAGE, 20 | imageId 21 | }; 22 | } 23 | 24 | const receiveReligionData = (dataObj) => { 25 | return { 26 | type: RECEIVE_RELIGION_DATA, 27 | dataObj 28 | }; 29 | }; 30 | 31 | const receiveOccupationData = (dataObj) => { 32 | return { 33 | type: RECEIVE_OCCUPATION_DATA, 34 | dataObj 35 | }; 36 | }; 37 | 38 | const receiveIncomeData = (dataObj) => { 39 | return { 40 | type: RECEIVE_INCOME_DATA, 41 | dataObj 42 | }; 43 | }; 44 | 45 | const receiveEthnicityData = (dataObj) => { 46 | return { 47 | type: RECEIVE_ETHNICITY_DATA, 48 | dataObj 49 | }; 50 | }; 51 | 52 | const receiveEducationData = (dataObj) => { 53 | return { 54 | type: RECEIVE_EDUCATION_DATA, 55 | dataObj 56 | }; 57 | }; 58 | 59 | const receiveMaritalData = (dataObj) => { 60 | return { 61 | type: RECEIVE_MARITAL_DATA, 62 | dataObj 63 | }; 64 | }; 65 | 66 | const receiveZipCodeData = (dataObj) => { 67 | return { 68 | type: RECEIVE_ZIP_CODE_DATA, 69 | dataObj 70 | }; 71 | }; 72 | 73 | const receiveGenderData = (dataObj) => { 74 | return { 75 | type: RECEIVE_GENDER_DATA, 76 | dataObj 77 | }; 78 | }; 79 | 80 | /* ----------------- DISPATCHERS ------------------ */ 81 | 82 | export const fetchReligionData = (religion) => dispatch => { 83 | axios.get(`https://solace-admin.herokuapp.com/api/admin/religion/${religion}`) 84 | .then(response => { 85 | dispatch(receiveReligionData(response.data)); 86 | }) 87 | .catch(err => console.error('failed to get religion data', err)); 88 | }; 89 | 90 | export const fetchOccupationData = (occupation) => dispatch => { 91 | axios.get(`https://solace-admin.herokuapp.com/api/admin/occupation/${occupation}`) 92 | .then(response => { 93 | dispatch(receiveOccupationData(response.data)); 94 | }) 95 | .catch(err => console.error('failed to get occupation data', err)); 96 | }; 97 | 98 | export const fetchIncomeData = (income) => dispatch => { 99 | axios.get(`https://solace-admin.herokuapp.com/api/admin/incomeLevel/${income}`) 100 | .then(response => { 101 | dispatch(receiveIncomeData(response.data)); 102 | }) 103 | .catch(err => console.error('failed to get income data', err)); 104 | }; 105 | 106 | export const fetchEthnicityData = (ethnicity) => dispatch => { 107 | axios.get(`https://solace-admin.herokuapp.com/api/admin/ethnicity/${ethnicity}`) 108 | .then(response => { 109 | dispatch(receiveEthnicityData(response.data)); 110 | }) 111 | .catch(err => console.error('failed to get ethnicity data', err)); 112 | }; 113 | 114 | export const fetchEducationData = (education) => dispatch => { 115 | axios.get(`https://solace-admin.herokuapp.com/api/admin/education/${education}`) 116 | .then(response => { 117 | dispatch(receiveEducationData(response.data)); 118 | }) 119 | .catch(err => console.error('failed to get education data', err)); 120 | }; 121 | 122 | export const fetchMaritalData = (marital) => dispatch => { 123 | axios.get(`https://solace-admin.herokuapp.com/api/admin/maritalStatus/${marital}`) 124 | .then(response => { 125 | dispatch(receiveMaritalData(response.data)); 126 | }) 127 | .catch(err => console.error('failed to get marital data', err)); 128 | }; 129 | 130 | export const fetchZipCodeData = (zipCode) => dispatch => { 131 | axios.get(`https://solace-admin.herokuapp.com/api/admin/zipCode/${zipCode}`) 132 | .then(response => { 133 | dispatch(receiveZipCodeData(response.data)); 134 | }) 135 | .catch(err => console.error('failed to get zip code data', err)); 136 | }; 137 | 138 | export const fetchGenderData = (gender) => dispatch => { 139 | axios.get(`https://solace-admin.herokuapp.com/api/admin/gender/${gender}`) 140 | .then(response => { 141 | dispatch(receiveGenderData(response.data)); 142 | }) 143 | .catch(err => console.error('failed to get gender data', err)); 144 | }; 145 | 146 | /* ----------------- REDUCER ------------------ */ 147 | 148 | const initialState = { 149 | religionData: {}, 150 | occupationData: {}, 151 | incomeData: {}, 152 | ethnicityData: {}, 153 | educationData: {}, 154 | maritalData: {}, 155 | zipCodeData: {}, 156 | genderData: {}, 157 | imageId: 1 158 | }; 159 | 160 | export default function adminReducer (state = initialState, action) { 161 | switch (action.type) { 162 | case RECEIVE_RELIGION_DATA: 163 | return Object.assign({}, state, { religionData: action.dataObj }); 164 | case RECEIVE_OCCUPATION_DATA: 165 | return Object.assign({}, state, { occupationData: action.dataObj }); 166 | case RECEIVE_INCOME_DATA: 167 | return Object.assign({}, state, { incomeData: action.dataObj }); 168 | case RECEIVE_ETHNICITY_DATA: 169 | return Object.assign({}, state, { ethnicityData: action.dataObj }); 170 | case RECEIVE_EDUCATION_DATA: 171 | return Object.assign({}, state, { educationData: action.dataObj }); 172 | case RECEIVE_MARITAL_DATA: 173 | return Object.assign({}, state, { maritalData: action.dataObj }); 174 | case RECEIVE_ZIP_CODE_DATA: 175 | return Object.assign({}, state, { zipCodeData: action.dataObj }); 176 | case RECEIVE_GENDER_DATA: 177 | return Object.assign({}, state, { genderData: action.dataObj }); 178 | case GET_IMAGE: 179 | return Object.assign({}, state, { imageId: action.imageId }); 180 | default: 181 | return state; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/native/reducer/index.native.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import adminReducer from './admin.native'; 3 | import questionsReducer from './questions.native'; 4 | import quoteReducer from './quote.native'; 5 | import recordingsReducer from './recordings.native'; 6 | import userReducer from './user.native'; 7 | 8 | const rootReducer = combineReducers({ 9 | admin: adminReducer, 10 | questions: questionsReducer, 11 | recordings: recordingsReducer, 12 | user: userReducer, 13 | quote: quoteReducer 14 | }); 15 | 16 | export default rootReducer; 17 | -------------------------------------------------------------------------------- /src/native/reducer/questions.native.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | /* ----------------- ACTIONS ------------------ */ 4 | 5 | const RECEIVE_THREE_QUESTIONS = 'RECEIVE_THREE_QUESTIONS' 6 | 7 | /* ------------ ACTION CREATORS ------------------ */ 8 | 9 | 10 | const receiveThreeQuestions = (questions) => { 11 | return { 12 | type: RECEIVE_THREE_QUESTIONS, 13 | questions 14 | } 15 | } 16 | 17 | /* ------------ REDUCER ------------------ */ 18 | 19 | export default function questionsReducer (questions = [], action) { 20 | switch (action.type) { 21 | case RECEIVE_THREE_QUESTIONS: 22 | return action.questions; 23 | default: 24 | return questions; 25 | } 26 | } 27 | 28 | /* ------------ DISPATCHERS ------------------ */ 29 | 30 | export const fetchThreeQuestions = () => dispatch => { 31 | axios.get(`https://solace-admin.herokuapp.com/api/questions`) 32 | .then(res=> res.data) 33 | .then(questions => { 34 | dispatch(receiveThreeQuestions(questions)); 35 | }) 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/native/reducer/quote.native.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | /* ----------------- ACTIONS ------------------ */ 4 | 5 | const RECEIVE_A_QUOTE = 'RECEIVE_A_QUOTE' 6 | 7 | /* ------------ ACTION CREATORS ------------------ */ 8 | 9 | 10 | const receiveAQuote = (quote) => { 11 | return { 12 | type: RECEIVE_A_QUOTE, 13 | quote: quote[0] 14 | } 15 | } 16 | 17 | 18 | /* ------------ REDUCER ------------------ */ 19 | 20 | export default function quotesReducer (quote = {}, action) { 21 | switch (action.type) { 22 | case RECEIVE_A_QUOTE: 23 | return action.quote; 24 | default: 25 | return quote; 26 | } 27 | } 28 | 29 | /* ------------ DISPATCHERS ------------------ */ 30 | 31 | export const fetchAQuote = () => dispatch => { 32 | axios.get(`https://solace-admin.herokuapp.com/api/questions/quote`) 33 | .then(res=> res.data) 34 | .then(quote => { 35 | dispatch(receiveAQuote(quote)); 36 | }) 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/native/reducer/recordings.native.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { Actions } from 'react-native-router-flux'; 3 | 4 | /* ----------------- ACTIONS ------------------ */ 5 | 6 | const RECEIVE_LATEST_RECORDINGS = 'RECEIVE_LATEST_RECORDINGS'; 7 | const RECEIVE_WEEKLY_AVG_RECORDINGS = 'RECEIVE_WEEKLY_AVG_RECORDINGS'; 8 | const RECEIVE_MONTHLY_AVG_RECORDINGS = 'RECEIVE_MONTHLY_AVG_RECORDINGS'; 9 | const RECEIVE_ALL_AVG_RECORDINGS = 'RECEIVE_ALL_AVG_RECORDINGS'; 10 | const RECEIVE_WEEKLY_TOTAL_RECORDINGS = 'RECEIVE_WEEKLY_TOTAL_RECORDINGS'; 11 | const RECEIVE_MONTHLY_TOTAL_RECORDINGS = 'RECEIVE_MONTHLY_TOTAL_RECORDINGS'; 12 | const RECEIVE_ALL_TOTAL_RECORDINGS = 'RECEIVE_ALL_TOTAL_RECORDINGS'; 13 | 14 | /* ----------------- ACTION CREATORS ------------------ */ 15 | 16 | const receiveLatestRecordings = (recordings) => { 17 | return { 18 | type: RECEIVE_LATEST_RECORDINGS, 19 | recordings 20 | }; 21 | }; 22 | 23 | const receiveWeeklyAvgRecordings = (recordings) => { 24 | return { 25 | type: RECEIVE_WEEKLY_AVG_RECORDINGS, 26 | recordings 27 | }; 28 | }; 29 | 30 | const receiveMonthlyAvgRecordings = (recordings) => { 31 | return { 32 | type: RECEIVE_MONTHLY_AVG_RECORDINGS, 33 | recordings 34 | }; 35 | }; 36 | 37 | const receiveAllAvgRecordings = (recordings) => { 38 | return { 39 | type: RECEIVE_ALL_AVG_RECORDINGS, 40 | recordings 41 | }; 42 | }; 43 | 44 | const receiveWeeklyTotalRecordings = (recordings) => { 45 | return { 46 | type: RECEIVE_WEEKLY_TOTAL_RECORDINGS, 47 | recordings 48 | }; 49 | }; 50 | 51 | const receiveMonthlyTotalRecordings = (recordings) => { 52 | return { 53 | type: RECEIVE_MONTHLY_TOTAL_RECORDINGS, 54 | recordings 55 | }; 56 | }; 57 | 58 | const receiveAllTotalRecordings = (recordings) => { 59 | return { 60 | type: RECEIVE_ALL_TOTAL_RECORDINGS, 61 | recordings 62 | }; 63 | }; 64 | 65 | /* ----------------- DISPATCHERS ------------------ */ 66 | 67 | export const fetchLatestRecordings = (userId) => dispatch => { 68 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/singlerecording`) 69 | .then(response => { 70 | dispatch(receiveLatestRecordings(response.data)); 71 | }) 72 | .catch(err => console.error('failed to get latest recordings', err)); 73 | }; 74 | 75 | export const fetchWeeklyAvgRecordings = (userId) => dispatch => { 76 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/weekrecordings/average`) 77 | .then(response => { 78 | dispatch(receiveWeeklyAvgRecordings(response.data)); 79 | }) 80 | .catch(err => console.error('failed to get weekly average recordings', err)); 81 | }; 82 | 83 | export const fetchMonthlyAvgRecordings = (userId) => dispatch => { 84 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/monthrecordings/average`) 85 | .then(response => { 86 | dispatch(receiveMonthlyAvgRecordings(response.data)); 87 | }) 88 | .then(() => Actions.monthlyAverage()) 89 | .catch(err => console.error('failed to get monthly average recordings', err)); 90 | }; 91 | 92 | export const fetchAllAvgRecordings = (userId) => dispatch => { 93 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/allrecordings/average`) 94 | .then(response => { 95 | dispatch(receiveAllAvgRecordings(response.data)); 96 | }) 97 | .then(() => Actions.allTimeAverage()) 98 | .catch(err => console.error('failed to get all average recordings', err)); 99 | }; 100 | 101 | export const fetchWeeklyTotalRecordings = (userId) => dispatch => { 102 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/weekrecordings`) 103 | .then(response => { 104 | dispatch(receiveWeeklyTotalRecordings(response.data)); 105 | }) 106 | .then(() => Actions.weeklyTotal()) 107 | .catch(err => console.error('failed to get weekly total recordings', err)); 108 | }; 109 | 110 | export const fetchMonthlyTotalRecordings = (userId) => dispatch => { 111 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/monthrecordings`) 112 | .then(response => { 113 | dispatch(receiveMonthlyTotalRecordings(response.data)); 114 | }) 115 | .then(() => Actions.monthlyTotal()) 116 | .catch(err => console.error('failed to get monthly total recordings', err)); 117 | }; 118 | 119 | export const fetchAllTotalRecordings = (userId) => dispatch => { 120 | axios.get(`https://solace-admin.herokuapp.com/api/users/${userId}/allrecordings`) 121 | .then(response => { 122 | dispatch(receiveAllTotalRecordings(response.data)); 123 | }) 124 | .then(() => Actions.allTimeTotal()) 125 | .catch(err => console.error('failed to get all total recordings', err)); 126 | }; 127 | 128 | /* ----------------- REDUCER ------------------ */ 129 | 130 | const initialState = { 131 | latestRecordings: {}, 132 | weeklyAvgRecordings: {}, 133 | monthlyAvgRecordings: {}, 134 | allAvgRecordings: {}, 135 | weeklyTotalRecordings: {}, 136 | monthlyTotalRecordings: {}, 137 | allTotalRecordings: {} 138 | }; 139 | 140 | export default function recordingsReducer (state = initialState, action) { 141 | switch (action.type) { 142 | case RECEIVE_LATEST_RECORDINGS: 143 | return Object.assign({}, state, { latestRecordings: action.recordings }); 144 | case RECEIVE_WEEKLY_AVG_RECORDINGS: 145 | return Object.assign({}, state, { weeklyAvgRecordings: action.recordings }); 146 | case RECEIVE_MONTHLY_AVG_RECORDINGS: 147 | return Object.assign({}, state, { monthlyAvgRecordings: action.recordings }); 148 | case RECEIVE_ALL_AVG_RECORDINGS: 149 | return Object.assign({}, state, { allAvgRecordings: action.recordings }); 150 | case RECEIVE_WEEKLY_TOTAL_RECORDINGS: 151 | return Object.assign({}, state, { weeklyTotalRecordings: action.recordings }); 152 | case RECEIVE_MONTHLY_TOTAL_RECORDINGS: 153 | return Object.assign({}, state, { monthlyTotalRecordings: action.recordings }); 154 | case RECEIVE_ALL_TOTAL_RECORDINGS: 155 | return Object.assign({}, state, { allTotalRecordings: action.recordings }); 156 | default: 157 | return state; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/native/reducer/user.native.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { Actions } from 'react-native-router-flux'; 3 | import { AlertIOS, AsyncStorage } from 'react-native'; 4 | 5 | 6 | 7 | /* ----------------- ACTIONS ------------------ */ 8 | 9 | const CREATE_USER = 'CREATE_USER'; 10 | const SET_CURRENT_USER = 'SET_CURRENT_USER'; 11 | const UPDATE_USER = 'UPDATE_USER'; 12 | const REMOVE_USER = 'REMOVE_USER'; 13 | 14 | 15 | /* ----------------- ACTION CREATORS ------------------ */ 16 | 17 | export const newUser = (createdUser) => { 18 | return { 19 | type: CREATE_USER, 20 | createdUser 21 | }; 22 | }; 23 | 24 | 25 | export const currentUser = (authenticatedUser) => { 26 | return { 27 | type: SET_CURRENT_USER, 28 | authenticatedUser 29 | }; 30 | }; 31 | 32 | export const updateUser = (updatedUser) => { 33 | return { 34 | type: UPDATE_USER, 35 | updatedUser 36 | }; 37 | }; 38 | 39 | export const removeUser = () => { 40 | return { 41 | type: REMOVE_USER 42 | }; 43 | }; 44 | 45 | /* ----------------- DISPATCHERS ------------------ */ 46 | 47 | export const updateCurrentUser = (id, credentials) => dispatch => { 48 | axios.put(`https://solace-admin.herokuapp.com/api/users/${id}`, credentials) 49 | .then(response => { 50 | const user = response.data; 51 | dispatch(updateUser(user)); 52 | Actions.homepage() 53 | }) 54 | .catch(err => console.error('unable to update', err)); 55 | }; 56 | 57 | export const logoutUser = () => dispatch => { 58 | AsyncStorage.removeItem('id_token') 59 | .then(removed => { 60 | dispatch(removeUser()), 61 | Actions.entryPoint(), 62 | AlertIOS.alert('Logout Success!') 63 | }) 64 | .catch(err => console.error('unable to logout', err)); 65 | }; 66 | 67 | 68 | /* ----------------- REDUCER ------------------ */ 69 | 70 | export default function userReducer (state = {}, action) { 71 | switch (action.type) { 72 | case CREATE_USER: 73 | return action.createdUser; 74 | case SET_CURRENT_USER: 75 | return action.authenticatedUser; 76 | case UPDATE_USER: 77 | return action.updatedUser; 78 | case REMOVE_USER: 79 | return {}; 80 | default: 81 | return state; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/native/screens/Account.native.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, Text, AlertIOS } from 'react-native'; 3 | import { Col, Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, List, ListItem, InputGroup, Input, Icon, Picker, Button } from 'native-base'; 5 | import { connect } from 'react-redux'; 6 | import { updateCurrentUser, logoutUser } from '../reducer/user.native'; 7 | import { BlurView } from 'react-native-blur'; 8 | import { occupation, income, ethnicity, religion, education, maritalStatus } from '../utils/dataList'; 9 | 10 | const Item = Picker.Item; 11 | 12 | class Account extends Component { 13 | constructor(props) { 14 | super(props); 15 | const { user } = this.props; 16 | this.state = { 17 | occupation: user.occupation || 'Select', 18 | incomeLevel: user.incomeLevel || 'Select', 19 | ethnicity: user.ethnicity || 'Select', 20 | religion: user.religion || 'Select', 21 | education: user.education || 'Select', 22 | maritalStatus: user.maritalStatus || 'Select', 23 | gender: user.gender || 'Select', 24 | zipCode: user.zipCode + '' || '', 25 | firstName: user.firstName, 26 | lastName: user.lastName, 27 | email: user.email 28 | }; 29 | this.onValueChange = this.onValueChange.bind(this); 30 | this.onPressUpdate = this.onPressUpdate.bind(this); 31 | this.mapOptionsList = this.mapOptionsList.bind(this); 32 | } 33 | 34 | onValueChange(value, type) { 35 | const category = type; 36 | this.setState({ [category]: value }); 37 | } 38 | 39 | onPressUpdate() { 40 | const { user, updateCurrentUser } = this.props; 41 | const infoToUpdate = {}; 42 | for (let props in this.state) { 43 | if (this.state[props] !== 'Select' && this.state[props]) { 44 | infoToUpdate[props] = props === 'zipCode' ? +this.state[props] : this.state[props]; 45 | } 46 | } 47 | 48 | updateCurrentUser(user.id, infoToUpdate); 49 | AlertIOS.alert("Update Successful!"); 50 | } 51 | 52 | mapOptionsList(optionsList){ 53 | return optionsList.map((option, i) => { 54 | return ( 55 | 56 | ); 57 | }); 58 | } 59 | 60 | render() { 61 | 62 | const { logoutUser } = this.props; 63 | 64 | let occupationList = this.mapOptionsList(occupation); 65 | let incomeList = this.mapOptionsList(income); 66 | let ethnicityList = this.mapOptionsList(ethnicity); 67 | let religionList = this.mapOptionsList(religion); 68 | let educationList = this.mapOptionsList(education); 69 | let maritalStatusList = this.mapOptionsList(maritalStatus); 70 | 71 | 72 | return ( 73 | 74 | 75 | 76 | 77 | 78 | Profile 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | this.setState({ firstName })} 94 | returnKeyType="next" 95 | onSubmitEditing={() => this.refs.lastName._textInput.focus()} 96 | /> 97 | 98 | 99 | 100 | 101 | 102 | this.refs.email._textInput.focus()} 106 | style={styles.textInput} 107 | placeholderTextColor= "#C7C7CD" 108 | placeholder="Last Name" 109 | value={this.state.lastName} 110 | onChangeText={(lastName) => this.setState({ lastName })} 111 | /> 112 | 113 | 114 | 115 | 116 | 117 | this.refs.zipCode._textInput.focus()} 121 | style={styles.textInput} 122 | placeholderTextColor= "#C7C7CD" 123 | placeholder="Email" 124 | value={this.state.email} 125 | onChangeText={(email) => this.setState({ email })} 126 | /> 127 | 128 | 129 | 130 | 131 | 132 | this.setState({ zipCode })} 141 | /> 142 | 143 | 144 | 145 | 146 | Occupation 147 | this.onValueChange(val, 'occupation') } > 152 | {occupationList} 153 | 154 | 155 | 156 | 157 | Income 158 | this.onValueChange(val, 'incomeLevel') } > 163 | {incomeList} 164 | 165 | 166 | 167 | 168 | Ethnicity 169 | this.onValueChange(val, 'ethnicity') } > 174 | {ethnicityList} 175 | 176 | 177 | 178 | 179 | Religion 180 | this.onValueChange(val, 'religion') } > 185 | {religionList} 186 | 187 | 188 | 189 | 190 | Education 191 | this.onValueChange(val, 'education') } > 196 | {educationList} 197 | 198 | 199 | 200 | 201 | Marital Status 202 | this.onValueChange(val, 'maritalStatus') } > 207 | {maritalStatusList} 208 | 209 | 210 | 211 | 212 | Gender 213 | this.onValueChange(val, 'gender') } > 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 229 | 230 | 231 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | ); 241 | } 242 | } 243 | 244 | 245 | const styles = StyleSheet.create({ 246 | blurContainer: { 247 | flex: 1, 248 | justifyContent: 'center', 249 | alignItems: 'stretch', 250 | backgroundColor: 'transparent', 251 | paddingHorizontal: 10 252 | }, 253 | content: { 254 | padding: 8, 255 | marginLeft: -2, 256 | marginRight: 12 257 | }, 258 | list: { 259 | padding: 8, 260 | marginRight: 12 261 | }, 262 | text: { 263 | fontSize: 16, 264 | fontFamily: 'Helvetica', 265 | color: 'white', 266 | marginLeft: 5, 267 | fontWeight: 'bold' 268 | }, 269 | textInput: { 270 | color: '#A9A9A9', 271 | fontSize: 16, 272 | fontFamily: 'Helvetica' 273 | }, 274 | inputField: { 275 | fontSize: 30, 276 | textAlign: 'center', 277 | fontFamily: 'Helvetica', 278 | color: 'white', 279 | marginTop: 40, 280 | marginBottom: 20, 281 | fontWeight: 'bold' 282 | }, 283 | button: { 284 | height: 72, 285 | width: 74, 286 | alignSelf: 'center', 287 | marginTop: 20, 288 | marginBottom: 30, 289 | borderRadius: 37 290 | } 291 | }); 292 | 293 | /* ----------------- CONTAINER ------------------ */ 294 | 295 | const mapStateToProps = (state) => { 296 | return { 297 | user: state.user 298 | }; 299 | }; 300 | 301 | const mapDispatchToProps = ({ updateCurrentUser, logoutUser }); 302 | 303 | export default connect(mapStateToProps, mapDispatchToProps)(Account); 304 | -------------------------------------------------------------------------------- /src/native/screens/CompleteProfile.native.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, Text, Image, View, AlertIOS} from 'react-native'; 3 | import { Col, Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, List, ListItem, InputGroup, Input, Icon, Picker, Button } from 'native-base'; 5 | import { Actions } from 'react-native-router-flux'; 6 | import { connect } from 'react-redux'; 7 | import { updateCurrentUser } from '../reducer/user.native'; 8 | import { BlurView } from 'react-native-blur'; 9 | import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; 10 | import Spinner from 'react-native-spinkit'; 11 | import {occupation, income, ethnicity, religion, education, maritalStatus } from '../utils/dataList'; 12 | 13 | const Item = Picker.Item; 14 | 15 | class CompleteProfile extends Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | occupation: 'Select', 20 | incomeLevel: 'Select', 21 | ethnicity: 'Select', 22 | religion: 'Select', 23 | education: 'Select', 24 | maritalStatus: 'Select', 25 | gender: 'Select', 26 | zipCode: '', 27 | loading: true 28 | }; 29 | this.onValueChange = this.onValueChange.bind(this); 30 | this.onPressUpdate = this.onPressUpdate.bind(this); 31 | this.loadSpinner = this.loadSpinner.bind(this); 32 | this.mapOptionsList = this.mapOptionsList.bind(this); 33 | } 34 | 35 | onValueChange(value, type) { 36 | const category = type; 37 | this.setState({ [category]: value }); 38 | } 39 | 40 | onPressUpdate() { 41 | const { loggedInUser, updateCurrentUser } = this.props; 42 | const infoToUpdate = {}; 43 | for (let props in this.state) { 44 | if (this.state[props] !== 'Select' && this.state[props] && props !== 'loading') { 45 | infoToUpdate[props] = props === 'zipCode' ? +this.state[props] : this.state[props]; 46 | } 47 | } 48 | 49 | updateCurrentUser(loggedInUser.id, infoToUpdate); 50 | AlertIOS.alert('Profile Updated!') 51 | } 52 | 53 | loadSpinner() { 54 | this.setState({ loading: !this.state.loading }) 55 | } 56 | 57 | mapOptionsList(optionsList){ 58 | return optionsList.map((option, i) => { 59 | return ( 60 | 61 | ); 62 | }); 63 | }; 64 | 65 | render() { 66 | 67 | let occupationList = this.mapOptionsList(occupation); 68 | let incomeList = this.mapOptionsList(income); 69 | let ethnicityList = this.mapOptionsList(ethnicity); 70 | let religionList = this.mapOptionsList(religion); 71 | let educationList = this.mapOptionsList(education); 72 | let maritalStatusList = this.mapOptionsList(maritalStatus); 73 | 74 | return ( 75 | 76 | 77 | {this.state.loading ? 78 | ( 79 | 80 | ) 81 | : ( 82 | 83 | 84 | 85 | 86 | 87 | Complete your profile! 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | Occupation 97 | this.onValueChange(val, 'occupation') } > 102 | {occupationList} 103 | 104 | 105 | 106 | 107 | Income 108 | this.onValueChange(val, 'incomeLevel') } > 113 | {incomeList} 114 | 115 | 116 | 117 | 118 | Ethnicity 119 | this.onValueChange(val, 'ethnicity') } > 124 | {ethnicityList} 125 | 126 | 127 | 128 | 129 | Religion 130 | this.onValueChange(val, 'religion') } > 135 | {religionList} 136 | 137 | 138 | 139 | 140 | Education 141 | this.onValueChange(val, 'education') } > 146 | {educationList} 147 | 148 | 149 | 150 | 151 | Marital Status 152 | this.onValueChange(val, 'maritalStatus') } > 157 | {maritalStatusList} 158 | 159 | 160 | 161 | 162 | Gender 163 | this.onValueChange(val, 'gender') } > 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | this.setState({ zipCode })} 184 | /> 185 | 186 | 187 | 188 | 189 | 190 | 193 | 194 | 195 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | )} 205 | 206 | 207 | ); 208 | } 209 | } 210 | 211 | 212 | const styles = StyleSheet.create({ 213 | img: { 214 | flex: 1, 215 | width: null, 216 | height: null, 217 | backgroundColor: 'rgba(0,0,0,0)', 218 | resizeMode: 'cover', 219 | position: 'absolute', 220 | left: 0, 221 | right: 0, 222 | top: 0, 223 | bottom: 0 224 | }, 225 | container: { 226 | flex: 1, 227 | justifyContent: 'center', 228 | alignItems: 'stretch', 229 | backgroundColor: 'transparent', 230 | }, 231 | blurContainer: { 232 | flex: 1, 233 | justifyContent: 'center', 234 | alignItems: 'stretch', 235 | backgroundColor: 'transparent', 236 | paddingHorizontal: 10 237 | }, 238 | content: { 239 | padding: 8, 240 | marginLeft: -2, 241 | marginRight: 12 242 | }, 243 | list: { 244 | padding: 8, 245 | marginRight: 12 246 | }, 247 | text: { 248 | fontSize: 16, 249 | fontFamily: 'Helvetica', 250 | color: 'white', 251 | marginLeft: 5, 252 | fontWeight: 'bold' 253 | }, 254 | textInput: { 255 | color: '#A9A9A9', 256 | fontSize: 16, 257 | fontFamily: 'Helvetica' 258 | }, 259 | inputField: { 260 | fontSize: 30, 261 | textAlign: 'center', 262 | fontFamily: 'Helvetica', 263 | color: 'white', 264 | fontWeight: 'bold' 265 | }, 266 | button: { 267 | height: 66, 268 | width: 70, 269 | alignSelf: 'center', 270 | marginTop: 20 271 | }, 272 | spinView: { 273 | alignItems: 'center', 274 | justifyContent: 'center', 275 | flex: 1, 276 | backgroundColor: 'black' 277 | } 278 | }); 279 | 280 | 281 | 282 | 283 | /* ----------------- CONTAINER ------------------ */ 284 | 285 | const mapStateToProps = (state) => { 286 | return { 287 | loggedInUser: state.user 288 | }; 289 | }; 290 | 291 | const mapDispatchToProps = ({ updateCurrentUser }); 292 | 293 | export default connect(mapStateToProps, mapDispatchToProps)(CompleteProfile); 294 | 295 | -------------------------------------------------------------------------------- /src/native/screens/Homepage.native.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { StyleSheet, Text, View, ScrollView, Image } from 'react-native'; 3 | import { Col, Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, InputGroup, Input, Icon, Button, Container, Footer, FooterTab } from 'native-base'; 5 | import { Actions } from 'react-native-router-flux'; 6 | import { connect } from 'react-redux'; 7 | import {AudioRecorder, AudioUtils} from 'react-native-audio'; 8 | import { RNS3 } from 'react-native-aws3'; 9 | import axios from 'axios' 10 | import secrets from './secrets.json'; 11 | import Charts from './chartScreens/Charts.native'; 12 | import Recording from './Recording.native.js'; 13 | import Account from './Account.native.js'; 14 | import { fetchAQuote } from '../reducer/quote.native'; 15 | import { getImageId } from '../reducer/admin.native'; 16 | import store from '../store.native'; 17 | import Spinner from 'react-native-spinkit'; 18 | 19 | class Homepage extends Component { 20 | 21 | constructor(props, context) { 22 | super(props, context); 23 | this.state = { 24 | statsActive: false, 25 | microphoneActive: true, 26 | personActive: false, 27 | imageId: 1, 28 | loading: true 29 | }; 30 | this.toggleStatsActiveButton = this.toggleStatsActiveButton.bind(this); 31 | this.toggleMicrophoneActiveButton = this.toggleMicrophoneActiveButton.bind(this); 32 | this.togglePersonActiveButton = this.togglePersonActiveButton.bind(this); 33 | this.loadSpinner = this.loadSpinner.bind(this); 34 | } 35 | 36 | toggleStatsActiveButton() { 37 | this.setState({ 38 | statsActive: true, 39 | microphoneActive: false, 40 | personActive: false 41 | }); 42 | } 43 | 44 | toggleMicrophoneActiveButton() { 45 | this.setState({ 46 | statsActive: false, 47 | microphoneActive: true, 48 | personActive: false 49 | }); 50 | } 51 | 52 | togglePersonActiveButton() { 53 | this.setState({ 54 | statsActive: false, 55 | microphoneActive: false, 56 | personActive: true 57 | }); 58 | } 59 | 60 | 61 | loadSpinner() { 62 | this.setState({ loading: !this.state.loading }); 63 | } 64 | 65 | 66 | componentWillMount() { 67 | // Get random background image 68 | let imageId = Math.floor(Math.random() * 24) + 1; 69 | this.setState({imageId}); 70 | store.dispatch(getImageId(imageId)); 71 | } 72 | 73 | componentDidMount() { 74 | // Get random quote 75 | store.dispatch(fetchAQuote()); 76 | 77 | // Make post request to send average data to Watson API 78 | const userId = this.props.user.id; 79 | 80 | axios.post(`https://solace-admin.herokuapp.com/api/users/${userId}/weekrecordings/average`) 81 | .then(response => console.log('weekly avg', response.data)) 82 | .catch(err => console.log('failed to post weekly average recordings', err)); 83 | 84 | axios.post(`https://solace-admin.herokuapp.com/api/users/${userId}/monthrecordings/average`) 85 | .then(response => console.log('monthly avg', response.data)) 86 | .catch(err => console.log('failed to post monthly average recordings', err)); 87 | 88 | axios.post(`https://solace-admin.herokuapp.com/api/users/${userId}/allrecordings/average`) 89 | .then(response => console.log('all avg', response.data)) 90 | .catch(err => console.log('failed to post all average recordings', err)); 91 | } 92 | 93 | render() { 94 | 95 | return ( 96 | 97 | 98 | {this.state.loading ? 99 | ( 100 | 101 | ) 102 | : this.state.statsActive ? : this.state.microphoneActive ? : } 103 |
104 | 105 | 106 | 107 | 108 | 109 |
110 | 111 |
112 | ); 113 | } 114 | } 115 | 116 | const styles = StyleSheet.create({ 117 | img: { 118 | flex: 1, 119 | width: null, 120 | height: null, 121 | backgroundColor: 'rgba(0,0,0,0)', 122 | resizeMode: 'cover', 123 | position: 'absolute', 124 | left: 0, 125 | right: 0, 126 | top: 0, 127 | bottom: 0 128 | }, 129 | container: { 130 | flex: 1, 131 | justifyContent: 'center', 132 | alignItems: 'stretch', 133 | backgroundColor: 'transparent', 134 | }, 135 | spinView: { 136 | alignItems: 'center', 137 | justifyContent: 'center', 138 | flex: 1, 139 | backgroundColor: 'black' 140 | } 141 | }); 142 | 143 | /* ----------------- CONTAINER ------------------ */ 144 | 145 | const mapStateToProps = (state) => { 146 | return { 147 | user: state.user 148 | }; 149 | }; 150 | 151 | export default connect(mapStateToProps)(Homepage); 152 | -------------------------------------------------------------------------------- /src/native/screens/Login.native.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { StyleSheet, Text, View, Dimensions, Image, AlertIOS, AsyncStorage } from 'react-native'; 3 | import { Col, Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, InputGroup, Input, Icon, Button } from 'native-base'; 5 | import { Actions, ActionConst } from 'react-native-router-flux'; 6 | import { connect } from 'react-redux'; 7 | import { currentUser } from '../reducer/user.native' 8 | import store from '../store.native'; 9 | import { checkEmail } from '../utils/validation'; 10 | import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; 11 | import Spinner from 'react-native-spinkit'; 12 | 13 | const STORAGE_KEY = 'id_token'; 14 | 15 | class Login extends Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | email: '', 20 | password: '', 21 | loading: false 22 | }; 23 | 24 | this.onValueChange = this.onValueChange.bind(this); 25 | this._userLogin = this._userLogin.bind(this); 26 | } 27 | 28 | async onValueChange(item, selectedValue) { 29 | try { 30 | await AsyncStorage.setItem(item, selectedValue); 31 | } catch (error) { 32 | console.log('AsyncStorage error: ' + error.message); 33 | } 34 | } 35 | 36 | _userLogin() { 37 | const { email, password } = this.state; 38 | let value = {email, password}; 39 | this.setState({ loading: true }); 40 | if (value) { // if validation fails, value will be null 41 | fetch("https://solace-admin.herokuapp.com/api/tokens/sessions/create", { 42 | method: "POST", 43 | headers: { 44 | 'Accept': 'application/json', 45 | 'Content-Type': 'application/json' 46 | }, 47 | body: JSON.stringify({ 48 | email: value.email, 49 | password: value.password, 50 | }) 51 | }) 52 | .then((response) => response.json()) 53 | .then((responseData) => { 54 | if(!responseData.id_token) { 55 | AlertIOS.alert("Invalid Username") 56 | this.setState({ loading: false }); 57 | } else { 58 | console.log('this is the response', responseData), 59 | this.onValueChange(STORAGE_KEY, responseData.id_token), 60 | store.dispatch(currentUser(responseData.user)), 61 | Actions.homepage() 62 | } 63 | }) 64 | .catch(err => { 65 | this.setState({ loading: false }); 66 | AlertIOS.alert("Invalid Password") 67 | }) 68 | .done(); 69 | } 70 | } 71 | 72 | render() { 73 | return ( 74 | 75 | {!this.state.loading ? 76 | ( 77 | 78 | 79 | 80 | 81 | 82 | 83 | this.setState({ email })} 90 | style={styles.inputField} 91 | onSubmitEditing={() => this.refs.password._textInput.focus()} 92 | /> 93 | {this.state.email === '' ? null : checkEmail(this.state.email) ? : } 94 | 95 | 96 | 97 | this.setState({ password })} 107 | style={styles.inputField} 108 | onSubmitEditing={this._userLogin} 109 | /> 110 | 111 | 112 | 113 | 118 | 119 | 120 | 121 | 126 | 127 | 128 | ) 129 | : ( 130 | 131 | )} 132 | 133 | ); 134 | } 135 | } 136 | 137 | const styles = StyleSheet.create({ 138 | container: { 139 | flex: 1, 140 | width: null, 141 | height: null, 142 | backgroundColor: 'rgba(0,0,0,0)' 143 | }, 144 | content: { 145 | justifyContent: 'center', 146 | alignItems: 'center', 147 | position: 'relative', 148 | top: 80 149 | }, 150 | inputPosition: { 151 | position: 'relative', 152 | left: 0, 153 | right: 0, 154 | top: 324 155 | }, 156 | inputField: { 157 | fontSize: 18, 158 | fontFamily: 'Helvetica', 159 | color: 'white', 160 | fontWeight: 'bold' 161 | }, 162 | inputCreds: { 163 | paddingLeft: 15, 164 | marginBottom: 17, 165 | marginLeft: 20, 166 | marginRight: 20, 167 | backgroundColor: 'rgba(0,0,0,0.3)', 168 | borderColor: 'rgba(0,0,0,0)' 169 | }, 170 | account: { 171 | alignItems: 'flex-end', 172 | justifyContent: 'flex-end', 173 | paddingRight: 20, 174 | marginTop: 15 175 | }, 176 | login: { 177 | marginLeft: 20, 178 | marginRight: 20 179 | }, 180 | spinView: { 181 | alignItems: 'center', 182 | justifyContent: 'center', 183 | flex: 1 184 | } 185 | }); 186 | 187 | 188 | /* ----------------- CONTAINER ------------------ */ 189 | 190 | const mapStateToProps = (state) => { 191 | return { 192 | user: state.user 193 | }; 194 | }; 195 | 196 | export default connect(mapStateToProps)(Login); 197 | -------------------------------------------------------------------------------- /src/native/screens/Picker.native.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectsolace/solace-react-native/44c085d4cd0de65f1f1574f798132483d09b9563/src/native/screens/Picker.native.js -------------------------------------------------------------------------------- /src/native/screens/QuestionsModal.native.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, Text, View, Image } from 'react-native'; 3 | import { Icon } from 'native-base'; 4 | import { Actions } from 'react-native-router-flux'; 5 | import Swiper from 'react-native-swiper'; 6 | import store from '../store.native'; 7 | import { fetchThreeQuestions } from '../reducer/questions.native'; 8 | import { connect } from 'react-redux'; 9 | import { BlurView } from 'react-native-blur'; 10 | 11 | export class QuestionsModal extends Component { 12 | 13 | constructor(props){ 14 | super(props) 15 | } 16 | 17 | componentDidMount() { 18 | store.dispatch(fetchThreeQuestions()) 19 | } 20 | 21 | render(){ 22 | const { questions } = this.props; 23 | return ( 24 | 25 | 26 | 27 | { questions && questions.map(questionObj => ( 28 | 29 | 30 | {questionObj.question} 31 | 32 | ) 33 | )} 34 | 35 | 36 | 37 | ); 38 | } 39 | } 40 | 41 | const styles = StyleSheet.create({ 42 | container: { 43 | flex: 1, 44 | width: null, 45 | height: null, 46 | opacity: 0.85, 47 | }, 48 | closeButton: { 49 | fontSize: 30, 50 | textAlign: 'right', 51 | marginTop: 35, 52 | marginRight: 20, 53 | color: 'white', 54 | }, 55 | text: { 56 | color: 'white', 57 | fontSize: 25, 58 | marginLeft: 30, 59 | marginRight: 30, 60 | top: 225, 61 | textAlign: 'center', 62 | fontWeight: 'bold', 63 | shadowColor: '#000000', 64 | shadowOffset: { 65 | width: 0, 66 | height: 3 67 | }, 68 | shadowRadius: 5, 69 | shadowOpacity: 1.0 70 | } 71 | }); 72 | 73 | /* ----------------- CONTAINER ------------------ */ 74 | 75 | const mapStateToProps = (state) => { 76 | return { 77 | questions: state.questions, 78 | imageId: state.admin.imageId 79 | }; 80 | }; 81 | 82 | export default connect(mapStateToProps)(QuestionsModal); 83 | -------------------------------------------------------------------------------- /src/native/screens/Recording.native.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { StyleSheet, Text, View, Dimensions, Image, TouchableHighlight, TouchableOpacity, AlertIOS } from 'react-native'; 3 | import { Col, Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, InputGroup, Input, Icon, Button, Container, Footer, FooterTab } from 'native-base'; 5 | import { Actions } from 'react-native-router-flux'; 6 | import {AudioRecorder, AudioUtils} from 'react-native-audio'; 7 | import { RNS3 } from 'react-native-aws3'; 8 | import axios from 'axios' 9 | import secrets from './secrets.json'; 10 | import {connect} from 'react-redux' 11 | 12 | const formattedSeconds = (sec) => Math.floor(sec / 60) + ':' + ('0' + sec % 60).slice(-2); 13 | 14 | 15 | let audioPath = AudioUtils.DocumentDirectoryPath + '/watson2.wav'; 16 | 17 | AudioRecorder.prepareRecordingAtPath(audioPath, { 18 | SampleRate: 22050, 19 | Channels: 1, 20 | AudioQuality: "Low", 21 | AudioEncoding: "lpcm" 22 | }); 23 | 24 | class RecordingComponent extends Component { 25 | 26 | 27 | constructor(props, context) { 28 | super(props, context); 29 | this.state={ 30 | recording:false, 31 | stopwatchStart: false, 32 | totalDuration: 90000, 33 | stopwatchReset: false, 34 | time: 0, 35 | secondsElapsed: 0, 36 | lastClearedIncrementer: null 37 | } 38 | this.incrementer = null; 39 | this.handleStartClick = this.handleStartClick.bind(this) 40 | this.handleStopClick = this.handleStopClick.bind(this) 41 | this.handleResetClick = this.handleResetClick.bind(this) 42 | this.onStartRecord = this.onStartRecord.bind(this) 43 | this.onStopRecord = this.onStopRecord.bind(this) 44 | } 45 | 46 | componentWillUnmount(){ 47 | this.onStopRecord() 48 | } 49 | 50 | handleStartClick() { 51 | this.incrementer = setInterval( () => 52 | this.setState({ 53 | secondsElapsed: this.state.secondsElapsed + 1 54 | }) 55 | , 1000); 56 | } 57 | 58 | handleStopClick() { 59 | clearInterval(this.incrementer); 60 | this.setState({ 61 | lastClearedIncrementer: this.incrementer 62 | }); 63 | } 64 | 65 | handleResetClick() { 66 | clearInterval(this.incrementer); 67 | this.setState({ 68 | secondsElapsed: 0 69 | }); 70 | } 71 | 72 | onStartRecord(){ 73 | console.log('STARTED RECORDING') 74 | // AlertIOS.alert('Please Record For At Least One Minute') 75 | AudioRecorder.startRecording(); 76 | this.handleStartClick() 77 | this.setState({recording:true}) 78 | 79 | }; 80 | 81 | onStopRecord(){ 82 | if(this.state.recording) { 83 | AudioRecorder.stopRecording(); 84 | console.log('STOPPED RECORDING') 85 | let file = { 86 | // `uri` can also be a file system path (i.e. file://) 87 | uri: audioPath, 88 | name: `${this.props.user.id}/recording.wav`, 89 | type: "audio/wav" 90 | } 91 | let options = { 92 | keyPrefix: "/", 93 | bucket: "watsonapi", 94 | region: "us-east-1", 95 | accessKey: secrets.keyA, 96 | secretKey: secrets.keyB, 97 | successActionStatus: 201 98 | } 99 | 100 | RNS3.put(file, options) 101 | .then(response => { 102 | if (response.status !== 201) throw new Error("Failed to upload audio to S3"); 103 | console.log(response.body.postResponse.location); 104 | return axios.post('https://solace-admin.herokuapp.com/api/watson/', {userID:this.props.user.id}).then(function(resp){ 105 | console.log(resp.data) 106 | }) 107 | }) 108 | .catch(err => console.log(err)); 109 | 110 | this.handleStopClick() 111 | this.handleResetClick() 112 | this.setState({recording:false}) 113 | 114 | } 115 | }; 116 | 117 | render() { 118 | 119 | 120 | const recordingMic = () =>{ 121 | return ( 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | ) 130 | } 131 | 132 | const stopMic = () =>{ 133 | return ( 134 | 135 | 136 | 137 | 138 | 139 | {formattedSeconds(this.state.secondsElapsed)} 140 | 141 | 142 | 143 | 144 | ) 145 | } 146 | 147 | 148 | return ( 149 | 150 | 151 | 152 | {`Hello ${this.props.user.firstName}. \n What's on your mind today?`} 153 | {!this.state.recording ? recordingMic() : stopMic()} 154 | {`"${this.props.quote.quote}"`} 155 | 158 | 159 | ); 160 | } 161 | } 162 | 163 | const handleTimerComplete = () => alert("custom completion function"); 164 | 165 | const styles = StyleSheet.create({ 166 | image: { 167 | alignSelf: 'center', 168 | marginTop: 0, 169 | marginBottom: 50 170 | }, 171 | image2: { 172 | height: 100, 173 | width: 100, 174 | alignSelf: 'center', 175 | }, 176 | image3: { 177 | marginTop: 9, 178 | height: 67, 179 | width: 67, 180 | alignSelf: 'center' 181 | }, 182 | text: { 183 | alignSelf: 'center', 184 | color: 'white', 185 | textAlign: 'center', 186 | fontWeight: 'bold', 187 | shadowColor: '#000000', 188 | shadowOffset: { 189 | width: 0, 190 | height: 3, 191 | }, 192 | shadowRadius: 7, 193 | shadowOpacity: 1.0, 194 | marginBottom: 10, 195 | marginLeft: 15, 196 | marginRight: 15 197 | }, 198 | text2: { 199 | alignSelf: 'center', 200 | color: 'white', 201 | textAlign: 'center', 202 | fontWeight: 'bold', 203 | shadowColor: '#000000', 204 | shadowOffset: { 205 | width: 0, 206 | height: 3 207 | }, 208 | shadowRadius: 5, 209 | shadowOpacity: 1.0 210 | }, 211 | phantom: { 212 | height: 100 213 | }, 214 | phantom2: { 215 | height: 83.5 216 | }, 217 | timer: { 218 | alignSelf: 'center', 219 | color: 'white', 220 | fontSize: 23 221 | }, 222 | helpButton: { 223 | fontSize: 30, 224 | textAlign: 'right', 225 | marginTop: 35, 226 | marginRight: 20, 227 | marginBottom: 0, 228 | color: 'white' 229 | }, 230 | timerContainer: { 231 | marginTop: 13 232 | } 233 | }); 234 | 235 | /* ----------------- CONTAINER ------------------ */ 236 | 237 | const mapStateToProps = (state) => { 238 | return { 239 | user: state.user, 240 | quote:state.quote 241 | }; 242 | }; 243 | 244 | export default connect(mapStateToProps)(RecordingComponent); 245 | -------------------------------------------------------------------------------- /src/native/screens/Signup.native.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, Text, Image, AlertIOS, AsyncStorage, Dimensions } from 'react-native'; 3 | import { Row, Grid } from 'react-native-easy-grid'; 4 | import { Content, InputGroup, Input, Icon, Button } from 'native-base'; 5 | import { Actions } from 'react-native-router-flux'; 6 | import { newUser } from '../reducer/user.native'; 7 | import { connect } from 'react-redux'; 8 | import store from '../store.native'; 9 | import { checkEmail } from '../utils/validation'; 10 | import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; 11 | import Spinner from 'react-native-spinkit'; 12 | 13 | const STORAGE_KEY = 'id_token'; 14 | 15 | class Signup extends Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | firstName: '', 20 | lastName: '', 21 | password: '', 22 | email: '', 23 | loading: true, 24 | afterSignupLoad: false 25 | }; 26 | 27 | this.onValueChange = this.onValueChange.bind(this); 28 | this._userSignup = this._userSignup.bind(this); 29 | this.loadSpinner = this.loadSpinner.bind(this); 30 | } 31 | 32 | async onValueChange(item, selectedValue) { 33 | try { 34 | await AsyncStorage.setItem(item, selectedValue); 35 | } catch (error) { 36 | console.log('AsyncStorage error: ' + error.message); 37 | } 38 | } 39 | 40 | _userSignup() { 41 | const { firstName, lastName, password, email } = this.state; 42 | 43 | if(firstName && lastName && checkEmail(email) && password ){ 44 | 45 | let value = { 46 | firstName, 47 | lastName, 48 | password, 49 | email 50 | }; 51 | 52 | if (value) { // if validation fails, value will be null 53 | this.setState({ loading: true, afterSignupLoad: true }); 54 | fetch("https://solace-admin.herokuapp.com/api/tokens/signup", { 55 | method: "POST", 56 | headers: { 57 | 'Accept': 'application/json', 58 | 'Content-Type': 'application/json' 59 | }, 60 | body: JSON.stringify({ 61 | firstName: value.firstName, 62 | lastName: value.lastName, 63 | password: value.password, 64 | email: value.email 65 | }) 66 | }) 67 | .then((response) => response.json()) 68 | .then((responseData) => { 69 | this.onValueChange(STORAGE_KEY, responseData.id_token), 70 | store.dispatch(newUser(responseData.user)), 71 | Actions.completeProfile(); 72 | }) 73 | .catch(err => console.error('signup failed', err)) 74 | .done(); 75 | } 76 | } else { 77 | AlertIOS.alert("Invalid Input") 78 | } 79 | } 80 | 81 | loadSpinner() { 82 | this.setState({ loading: !this.state.loading }) 83 | } 84 | 85 | render() { 86 | 87 | return ( 88 | 89 | {this.state.loading ? 90 | ( 91 | 92 | ) 93 | : ( 94 | 95 | 96 | 97 | 98 | 99 | Let's get started! 100 | 101 | 102 | 103 | 104 | this.setState({ firstName })} 109 | placeholder="first name" 110 | placeholderTextColor="#F0FFFF" 111 | style={styles.inputField} 112 | onSubmitEditing={() => this.refs.lastName._textInput.focus()} 113 | /> 114 | {this.state.firstName !== '' ? : null } 115 | 116 | 117 | 118 | this.setState({ lastName })} 124 | placeholder="last name" 125 | placeholderTextColor="#F0FFFF" 126 | style={styles.inputField} 127 | onSubmitEditing={() => this.refs.email._textInput.focus()} 128 | /> 129 | {this.state.lastName !== '' ? : null } 130 | 131 | 132 | 133 | this.setState({ email })} 139 | placeholder="email" 140 | placeholderTextColor="#F0FFFF" 141 | style={styles.inputField} 142 | onSubmitEditing={() => this.refs.password._textInput.focus()} 143 | /> 144 | {this.state.email === '' ? null : checkEmail(this.state.email) ? : } 145 | 146 | 147 | 148 | this.setState({ password })} 155 | placeholder="password" 156 | placeholderTextColor="#F0FFFF" 157 | style={styles.inputField} 158 | onSubmitEditing={ this._userSignup } 159 | /> 160 | {this.state.password !== '' ? : null } 161 | 162 | 163 | 164 | 169 | 170 | 171 | )} 172 | 173 | ); 174 | } 175 | } 176 | 177 | const styles = StyleSheet.create({ 178 | container: { 179 | flex: 1, 180 | width: null, 181 | height: null, 182 | backgroundColor: 'rgba(0,0,0,0)', 183 | resizeMode: 'cover' 184 | }, 185 | content: { 186 | justifyContent: 'center', 187 | alignItems: 'center', 188 | margin: 30 189 | }, 190 | text: { 191 | fontSize: 26, 192 | fontFamily: 'Helvetica', 193 | color: 'white', 194 | fontWeight: 'bold' 195 | }, 196 | inputField: { 197 | fontSize: 18, 198 | fontFamily: 'Helvetica', 199 | color: 'white', 200 | fontWeight: 'bold' 201 | }, 202 | inputCreds: { 203 | paddingLeft: 15, 204 | marginBottom: 17, 205 | marginLeft: 20, 206 | marginRight: 20, 207 | backgroundColor: 'rgba(0,0,0,0.3)', 208 | borderColor: 'rgba(0,0,0,0)' 209 | }, 210 | login: { 211 | marginLeft: 20, 212 | marginRight: 20, 213 | marginTop: 40 214 | }, 215 | spinView: { 216 | alignItems: 'center', 217 | justifyContent: 'center', 218 | flex: 1, 219 | backgroundColor: 'black' 220 | }, 221 | loadView: { 222 | alignItems: 'center', 223 | justifyContent: 'center', 224 | flex: 1 225 | } 226 | }); 227 | 228 | 229 | /* ----------------- CONTAINER ------------------ */ 230 | 231 | const mapStateToProps = (state) => { 232 | return { 233 | loggedInUser: state.user 234 | }; 235 | }; 236 | 237 | export default connect(mapStateToProps)(Signup); 238 | -------------------------------------------------------------------------------- /src/native/screens/Tutorial.native.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { Button, Icon } from 'native-base'; 4 | import { Actions } from 'react-native-router-flux'; 5 | import Swiper from 'react-native-swiper'; 6 | import { connect } from 'react-redux'; 7 | 8 | export class Tutorial extends Component { 9 | constructor(props){ 10 | super(props) 11 | } 12 | 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | ); 43 | } 44 | } 45 | 46 | const styles = StyleSheet.create({ 47 | imageContainer: { 48 | flex: 1, 49 | alignItems: 'center' 50 | }, 51 | image: { 52 | flex: 1, 53 | resizeMode: 'contain' 54 | }, 55 | button: { 56 | marginTop: 35, 57 | marginLeft: 510 58 | } 59 | }); 60 | 61 | /* ----------------- CONTAINER ------------------ */ 62 | 63 | const mapStateToProps = (state) => { 64 | return { 65 | imageId: state.admin.imageId 66 | }; 67 | }; 68 | 69 | export default connect(mapStateToProps)(Tutorial); 70 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/AllTimeAverageChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import BarGraphSlides from '../../components/BarGraphSlides'; 6 | import { mapLabels, sortData } from '../../utils/chart'; 7 | 8 | const AllTimeAverageChart = ({personalityData, personalityLabels, toneData, toneLabels, imageId}) => { 9 | 10 | return ( 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | ) 24 | }; 25 | 26 | 27 | const styles = StyleSheet.create({ 28 | container: { 29 | flex: 1, 30 | justifyContent: 'center', 31 | alignItems: 'stretch', 32 | backgroundColor: 'transparent' 33 | }, 34 | img: { 35 | flex: 1, 36 | width: null, 37 | height: null, 38 | backgroundColor: 'rgba(0,0,0,0)', 39 | resizeMode: 'cover', 40 | position: 'absolute', 41 | left: 0, 42 | right: 0, 43 | top: 0, 44 | bottom: 0 45 | } 46 | }); 47 | 48 | 49 | /* ----------------- CONTAINER ------------------ */ 50 | 51 | const mapStateToProps = ({recordings, admin}) => { 52 | const allTimeAvgPersonality = recordings.allAvgRecordings.personality; 53 | const allTimeAvgTone = recordings.allAvgRecordings.tone; 54 | 55 | const personalityData = sortData(allTimeAvgPersonality); 56 | const personalityLabels = mapLabels(allTimeAvgPersonality); 57 | const toneData = sortData(allTimeAvgTone); 58 | const toneLabels = mapLabels(allTimeAvgTone); 59 | 60 | return { 61 | personalityData, 62 | personalityLabels, 63 | toneData, 64 | toneLabels, 65 | imageId: admin.imageId 66 | }; 67 | }; 68 | 69 | export default connect(mapStateToProps)(AllTimeAverageChart); 70 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/AllTimeTotalChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import LineGraphSlides from '../../components/LineGraphSlides.native'; 6 | import { filterTraits } from '../../utils/chart'; 7 | 8 | 9 | const AllTimeTotalChart = ({ personalityArray, toneArray, imageId }) => { 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | }; 21 | 22 | 23 | const styles = StyleSheet.create({ 24 | container: { 25 | flex: 1, 26 | justifyContent: 'center', 27 | alignItems: 'stretch', 28 | backgroundColor: 'transparent' 29 | }, 30 | img: { 31 | flex: 1, 32 | width: null, 33 | height: null, 34 | backgroundColor: 'rgba(0,0,0,0)', 35 | resizeMode: 'cover', 36 | position: 'absolute', 37 | left: 0, 38 | right: 0, 39 | top: 0, 40 | bottom: 0 41 | } 42 | }); 43 | 44 | 45 | /* ----------------- CONTAINER ------------------ */ 46 | 47 | const mapStateToProps = ({ recordings, admin }) => { 48 | const allTimePersonalityRecords = recordings.allTotalRecordings.personality; 49 | const personalityArray = filterTraits(allTimePersonalityRecords); 50 | 51 | return { 52 | personalityArray, 53 | toneArray: recordings.allTotalRecordings.tone, 54 | imageId: admin.imageId 55 | }; 56 | }; 57 | 58 | export default connect(mapStateToProps)(AllTimeTotalChart); 59 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/Charts.native.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | import { Col, Row } from 'react-native-easy-grid'; 4 | import { Content, Icon, Button } from 'native-base'; 5 | import { Actions } from 'react-native-router-flux'; 6 | import { connect } from 'react-redux'; 7 | import { fetchLatestRecordings, fetchWeeklyAvgRecordings, fetchMonthlyAvgRecordings, fetchAllAvgRecordings, fetchWeeklyTotalRecordings, fetchMonthlyTotalRecordings, fetchAllTotalRecordings} from '../../reducer/recordings.native'; 8 | import store from '../../store.native'; 9 | import Spinner from 'react-native-spinkit'; 10 | 11 | class Charts extends Component { 12 | constructor(props) { 13 | super(props); 14 | this.state = { 15 | loading: true 16 | }; 17 | this.getMonthlyAvgRecordings = this.getMonthlyAvgRecordings.bind(this); 18 | this.getAllTimeAvgRecordings = this.getAllTimeAvgRecordings.bind(this); 19 | this.getWeeklyTotalRecordings = this.getWeeklyTotalRecordings.bind(this); 20 | this.getMonthlyTotalRecordings = this.getMonthlyTotalRecordings.bind(this); 21 | this.getAllTimeTotalRecordings = this.getAllTimeTotalRecordings.bind(this); 22 | this.getLatestData = this.getLatestData.bind(this); 23 | this.getWeeklyAvg = this.getWeeklyAvg.bind(this); 24 | this.loadSpinner = this.loadSpinner.bind(this); 25 | } 26 | 27 | componentDidMount() { 28 | store.dispatch(fetchLatestRecordings(this.props.user.id)); 29 | store.dispatch(fetchWeeklyAvgRecordings(this.props.user.id)); 30 | this.setState({ loading: false }); 31 | } 32 | 33 | getLatestData() { 34 | this.setState({ loading: true }); 35 | setTimeout(() => { 36 | Actions.latestData(); 37 | this.setState({ loading: false }); 38 | }, 500); 39 | } 40 | 41 | getWeeklyAvg() { 42 | this.setState({ loading: true }); 43 | setTimeout(() => { 44 | Actions.weeklyAverage(); 45 | this.setState({ loading: false }); 46 | }, 500); 47 | } 48 | 49 | getMonthlyAvgRecordings() { 50 | this.setState({ loading: true }); 51 | store.dispatch(fetchMonthlyAvgRecordings(this.props.user.id)); 52 | setTimeout(() => { 53 | this.setState({ loading: false }); 54 | }, 1000); 55 | } 56 | 57 | getAllTimeAvgRecordings() { 58 | this.setState({ loading: true }); 59 | store.dispatch(fetchAllAvgRecordings(this.props.user.id)); 60 | setTimeout(() => { 61 | this.setState({ loading: false }); 62 | }, 1000); 63 | } 64 | 65 | getWeeklyTotalRecordings() { 66 | this.setState({ loading: true }); 67 | store.dispatch(fetchWeeklyTotalRecordings(this.props.user.id)); 68 | setTimeout(() => { 69 | this.setState({ loading: false }); 70 | }, 1000); 71 | } 72 | 73 | getMonthlyTotalRecordings() { 74 | this.setState({ loading: true }); 75 | store.dispatch(fetchMonthlyTotalRecordings(this.props.user.id)); 76 | setTimeout(() => { 77 | this.setState({ loading: false }) 78 | }, 1000); 79 | } 80 | 81 | getAllTimeTotalRecordings() { 82 | this.setState({ loading: true }); 83 | store.dispatch(fetchAllTotalRecordings(this.props.user.id)); 84 | setTimeout(() => { 85 | this.setState({ loading: false }); 86 | }, 1000); 87 | } 88 | 89 | loadSpinner() { 90 | this.setState({ loading: !this.state.loading }) 91 | } 92 | 93 | render() { 94 | return ( 95 | 96 | {!this.state.loading ? 97 | ( 98 | 99 | 100 | View Your Data 101 | 102 | 103 | 104 | 105 | 106 | 107 | { this.props.recordings.latestRecordings && this.props.recordings.latestRecordings.personality 108 | ? () 112 | : () 116 | } 117 | 118 | 119 | { this.props.recordings.weeklyAvgRecordings.created_at 120 | ? ( 121 | 122 | 126 | 130 | 134 | 135 | 136 | 140 | 144 | 148 | 149 | ) 150 | : ( 151 | 152 | 156 | 160 | 164 | 165 | 166 | 170 | 174 | 178 | 179 | ) 180 | } 181 | 182 | 183 | ) 184 | : ( 185 | 186 | )} 187 | 188 | ); 189 | } 190 | } 191 | 192 | const styles = StyleSheet.create({ 193 | content: { 194 | justifyContent: 'center', 195 | alignItems: 'center', 196 | marginTop: 100 197 | }, 198 | text: { 199 | color: 'white', 200 | fontSize: 30, 201 | fontWeight: 'bold', 202 | shadowColor: '#000000', 203 | shadowOffset: { 204 | height: 1 205 | }, 206 | shadowRadius: 2, 207 | shadowOpacity: 0.5 208 | }, 209 | button: { 210 | alignSelf: 'stretch', 211 | margin: 10 212 | }, 213 | spinView: { 214 | alignItems: 'center', 215 | justifyContent: 'center', 216 | top: 250 217 | } 218 | }); 219 | 220 | /* ----------------- CONTAINER ------------------ */ 221 | 222 | const mapStateToProps = (state) => { 223 | return { 224 | user: state.user, 225 | recordings: state.recordings 226 | }; 227 | }; 228 | 229 | export default connect(mapStateToProps)(Charts); 230 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/IntroToCharts.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, Text, View, Image } from 'react-native'; 3 | import { Button, Icon } from 'native-base'; 4 | import { Actions } from 'react-native-router-flux'; 5 | import Swiper from 'react-native-swiper'; 6 | import { connect } from 'react-redux'; 7 | import { BlurView } from 'react-native-blur'; 8 | 9 | const IntroToCharts = ({imageId}) => { 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | No data yet. {'\n'} 19 | Go ahead and start recording! {'\n'} 20 | Once you have some data... 21 | 22 | 23 | 24 | 25 | 26 | Click the "Average" options for more accurate data... 27 | 28 | 29 | 30 | 31 | Click the "Total" options to compare your data over time 32 | 33 | 36 | 37 | 38 | 39 | 40 | ); 41 | } 42 | 43 | 44 | const styles = StyleSheet.create({ 45 | container: { 46 | flex: 1, 47 | width: null, 48 | height: null, 49 | opacity: 0.85, 50 | }, 51 | closeButton: { 52 | fontSize: 30, 53 | textAlign: 'right', 54 | marginTop: 35, 55 | marginRight: 20, 56 | color: 'white', 57 | }, 58 | firstText: { 59 | alignSelf: 'center', 60 | fontSize: 20, 61 | color: 'white', 62 | marginLeft: 20, 63 | marginRight: 20, 64 | top: 225, 65 | textAlign: 'center', 66 | fontWeight: 'bold', 67 | shadowColor: '#000000', 68 | shadowOffset: { 69 | width: 0, 70 | height: 3 71 | }, 72 | shadowRadius: 5, 73 | shadowOpacity: 1.0 74 | }, 75 | secondText: { 76 | alignSelf: 'center', 77 | fontSize: 20, 78 | color: 'white', 79 | marginLeft: 20, 80 | marginRight: 20, 81 | top: 240, 82 | textAlign: 'center', 83 | fontWeight: 'bold', 84 | shadowColor: '#000000', 85 | shadowOffset: { 86 | width: 0, 87 | height: 3 88 | }, 89 | shadowRadius: 5, 90 | shadowOpacity: 1.0 91 | }, 92 | lastText: { 93 | alignSelf: 'center', 94 | fontSize: 20, 95 | color: 'white', 96 | marginLeft: 20, 97 | marginRight: 20, 98 | top: 300, 99 | textAlign: 'center', 100 | fontWeight: 'bold', 101 | shadowColor: '#000000', 102 | shadowOffset: { 103 | width: 0, 104 | height: 3 105 | }, 106 | shadowRadius: 5, 107 | shadowOpacity: 1.0 108 | }, 109 | button: { 110 | alignSelf: 'center', 111 | marginTop: 325 112 | } 113 | }); 114 | 115 | /* ----------------- CONTAINER ------------------ */ 116 | 117 | const mapStateToProps = (state) => { 118 | return { 119 | imageId: state.admin.imageId 120 | }; 121 | }; 122 | 123 | export default connect(mapStateToProps)(IntroToCharts); 124 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/LatestDataChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import BarGraphSlides from '../../components/BarGraphSlides'; 6 | import { mapLabels, sortData } from '../../utils/chart'; 7 | 8 | const LatestDataChart = ({personalityData, personalityLabels, toneData, toneLabels, imageId}) => { 9 | 10 | return ( 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | ) 24 | }; 25 | 26 | 27 | const styles = StyleSheet.create({ 28 | container: { 29 | flex: 1, 30 | justifyContent: 'center', 31 | alignItems: 'stretch', 32 | backgroundColor: 'transparent' 33 | }, 34 | img: { 35 | flex: 1, 36 | width: null, 37 | height: null, 38 | backgroundColor: 'rgba(0,0,0,0)', 39 | resizeMode: 'cover', 40 | position: 'absolute', 41 | left: 0, 42 | right: 0, 43 | top: 0, 44 | bottom: 0 45 | } 46 | }); 47 | 48 | 49 | /* ----------------- CONTAINER ------------------ */ 50 | 51 | const mapStateToProps = ({recordings, admin}) => { 52 | const latestPersonality = recordings.latestRecordings.personality; 53 | const latestTone = recordings.latestRecordings.tone; 54 | 55 | const personalityData = sortData(latestPersonality); 56 | const personalityLabels = mapLabels(latestPersonality); 57 | const toneData = sortData(latestTone); 58 | const toneLabels = mapLabels(latestTone); 59 | 60 | return { 61 | personalityData, 62 | personalityLabels, 63 | toneData, 64 | toneLabels, 65 | imageId: admin.imageId 66 | }; 67 | }; 68 | 69 | export default connect(mapStateToProps)(LatestDataChart); 70 | 71 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/MonthlyAverageChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import { mapLabels, sortData } from '../../utils/chart'; 6 | import BarGraphSlides from '../../components/BarGraphSlides'; 7 | 8 | 9 | const MonthlyAverageChart = ({ personalityData, personalityLabels, toneData, toneLabels, imageId }) => { 10 | return ( 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | ) 24 | } 25 | 26 | const styles = StyleSheet.create({ 27 | container: { 28 | flex: 1, 29 | justifyContent: 'center', 30 | alignItems: 'stretch', 31 | backgroundColor: 'transparent' 32 | }, 33 | img: { 34 | flex: 1, 35 | width: null, 36 | height: null, 37 | backgroundColor: 'rgba(0,0,0,0)', 38 | resizeMode: 'cover', 39 | position: 'absolute', 40 | left: 0, 41 | right: 0, 42 | top: 0, 43 | bottom: 0 44 | } 45 | }); 46 | 47 | 48 | /* ----------------- CONTAINER ------------------ */ 49 | 50 | const mapStateToProps = ({ recordings, admin }) => { 51 | const monthlyAvgPersonalityArray = recordings.monthlyAvgRecordings.personality; 52 | const monthlyAvgToneArray = recordings.monthlyAvgRecordings.tone; 53 | 54 | const personalityData = sortData(monthlyAvgPersonalityArray); 55 | const toneData = sortData(monthlyAvgToneArray); 56 | const personalityLabels = mapLabels(monthlyAvgPersonalityArray); 57 | const toneLabels = mapLabels(monthlyAvgToneArray); 58 | 59 | return { 60 | personalityData, 61 | toneData, 62 | personalityLabels, 63 | toneLabels, 64 | imageId: admin.imageId 65 | }; 66 | }; 67 | 68 | export default connect(mapStateToProps)(MonthlyAverageChart); 69 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/MonthlyTotalChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import { filterTraits } from '../../utils/chart'; 6 | import LineGraphSlides from '../../components/LineGraphSlides.native'; 7 | 8 | 9 | const MonthlyTotalChart = ({ imageId, personalityArray, toneArray }) => { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ) 19 | } 20 | 21 | 22 | const styles = StyleSheet.create({ 23 | container: { 24 | flex: 1, 25 | justifyContent: 'center', 26 | alignItems: 'stretch', 27 | backgroundColor: 'transparent' 28 | }, 29 | img: { 30 | flex: 1, 31 | width: null, 32 | height: null, 33 | backgroundColor: 'rgba(0,0,0,0)', 34 | resizeMode: 'cover', 35 | position: 'absolute', 36 | left: 0, 37 | right: 0, 38 | top: 0, 39 | bottom: 0 40 | } 41 | }); 42 | 43 | 44 | /* ----------------- CONTAINER ------------------ */ 45 | 46 | const mapStateToProps = ({ recordings, admin }) => { 47 | const monthlyPersonalityTraits = recordings.monthlyTotalRecordings.personality; 48 | const personalityArray = filterTraits(monthlyPersonalityTraits); 49 | 50 | return { 51 | personalityArray, 52 | toneArray: recordings.monthlyTotalRecordings.tone, 53 | imageId: admin.imageId 54 | }; 55 | }; 56 | 57 | export default connect(mapStateToProps)(MonthlyTotalChart); 58 | 59 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/WeeklyAverageChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image } from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import BarGraphSlides from '../../components/BarGraphSlides'; 6 | import { mapLabels, sortData } from '../../utils/chart'; 7 | 8 | 9 | const WeeklyAverageChart = ({personalityData, personalityLabels, toneData, toneLabels, imageId}) => { 10 | return ( 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | ) 24 | }; 25 | 26 | 27 | const styles = StyleSheet.create({ 28 | container: { 29 | flex: 1, 30 | justifyContent: 'center', 31 | alignItems: 'stretch', 32 | backgroundColor: 'transparent' 33 | }, 34 | img: { 35 | flex: 1, 36 | width: null, 37 | height: null, 38 | backgroundColor: 'rgba(0,0,0,0)', 39 | resizeMode: 'cover', 40 | position: 'absolute', 41 | left: 0, 42 | right: 0, 43 | top: 0, 44 | bottom: 0 45 | } 46 | }); 47 | 48 | 49 | /* ----------------- CONTAINER ------------------ */ 50 | 51 | const mapStateToProps = ({recordings, admin}) => { 52 | const weeklyAvgPersonality = recordings.weeklyAvgRecordings.personality; 53 | const weeklyAvgTone = recordings.weeklyAvgRecordings.tone; 54 | 55 | const personalityData = sortData(weeklyAvgPersonality); 56 | const personalityLabels = mapLabels(weeklyAvgPersonality); 57 | const toneData = sortData(weeklyAvgTone); 58 | const toneLabels = mapLabels(weeklyAvgTone); 59 | 60 | return { 61 | personalityData, 62 | personalityLabels, 63 | toneData, 64 | toneLabels, 65 | imageId: admin.imageId 66 | }; 67 | }; 68 | 69 | export default connect(mapStateToProps)(WeeklyAverageChart); 70 | -------------------------------------------------------------------------------- /src/native/screens/chartScreens/WeeklyTotalChart.native.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, Image} from 'react-native'; 3 | import { connect } from 'react-redux'; 4 | import { BlurView } from 'react-native-blur'; 5 | import { filterTraits } from '../../utils/chart'; 6 | import LineGraphSlides from '../../components/LineGraphSlides.native'; 7 | 8 | 9 | const WeeklyTotalChart = ({ personalityArray, toneArray, imageId }) => { 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | }; 21 | 22 | 23 | const styles = StyleSheet.create({ 24 | container: { 25 | flex: 1, 26 | justifyContent: 'center', 27 | alignItems: 'stretch', 28 | backgroundColor: 'transparent' 29 | }, 30 | img: { 31 | flex: 1, 32 | width: null, 33 | height: null, 34 | backgroundColor: 'rgba(0,0,0,0)', 35 | resizeMode: 'cover', 36 | position: 'absolute', 37 | left: 0, 38 | right: 0, 39 | top: 0, 40 | bottom: 0 41 | } 42 | }); 43 | 44 | 45 | /* ----------------- CONTAINER ------------------ */ 46 | 47 | const mapStateToProps = ({ recordings, admin }) => { 48 | const weeklyPersonalityRecordings = recordings.weeklyTotalRecordings.personality; 49 | const personalityArray = filterTraits(weeklyPersonalityRecordings); 50 | 51 | return { 52 | personalityArray, 53 | toneArray: recordings.weeklyTotalRecordings.tone, 54 | imageId: admin.imageId 55 | }; 56 | }; 57 | 58 | export default connect(mapStateToProps)(WeeklyTotalChart); 59 | -------------------------------------------------------------------------------- /src/native/store.native.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import rootReducer from './reducer/index.native'; 3 | import createLogger from 'redux-logger'; // https://github.com/evgenyrodionov/redux-logger 4 | import thunkMiddleware from 'redux-thunk'; // https://github.com/gaearon/redux-thunk 5 | 6 | export default createStore(rootReducer, applyMiddleware(thunkMiddleware, createLogger())); 7 | -------------------------------------------------------------------------------- /src/native/utils/chart.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import { VictoryChart, VictoryLine, VictoryTheme, VictoryLabel, VictoryAxis, Line } from 'victory-native'; 4 | 5 | export const colorArray = [ '#7D26CD','#0000EE','#6495ED','#68228B','#c06dff','#104E8B','#B0C4DE','#0000FF','#5D478B','#1E90FF','#F0F8FF','#AB82FF','#836FFF','#9932CC','#BCD2EE','#6E7B8B','#191970','#6A5ACD','#0000CD','#9A32CD','#B23AEE','#7A67EE','#6C7B8B','#9370DB','#7B68EE','#473C8B','#000080','#D15FEE','#9F79EE','#BA55D3','#4B0082','#778899','#4682B4','#483D8B','#3A5FCD','#7A378B','#8A2BE2','#4169E1','#63B8FF','#8470FF','#800080','#A2B5CD','#27408B','#9400D3','#1874CD','#551A8B' ]; 6 | 7 | export const personality = 'The scores you see are all percentiles. They are comparing you to the broader population. For example, a 90% on Extraversion does not mean that you are 90% extroverted. It means that for that single trait, you are more extroverted than 90% of the people in the population.'; 8 | 9 | export const emotional = 'Emotional tone measures different types of emotions and feelings that people express. For each tone, a score of less than 50% indicates that the tone is unlikely to be perceived in the recorded content. Likewise, a score greater than 75% indicates high likelihood that the tone will be perceived.'; 10 | 11 | export const language = 'Language tone describes perceived language style based on the recorded content. For each tone, a score of less than 50% indicates that the tone is unlikely to be perceived in the recorded content. Likewise, a score greater than 75% indicates high likelihood that the tone will be perceived.'; 12 | 13 | export const social = 'Social tone measures the social tendencies in the recorded content on five categories that are adopted from the Big Five personality model. For each tone, a score of less than 50% indicates that the tone is unlikely to be perceived in the recorded content. Likewise, a score greater than 75% indicates high likelihood that the tone will be perceived.'; 14 | 15 | export const tone = 'For each tone, a score of less than 50% indicates that the tone is unlikely to be perceived in the recorded content. Likewise, a score greater than 75% indicates a high likelihood that the tone will be perceived.'; 16 | 17 | export const personalityTitles = ['Personality Insights I', 'Personality Insights II', 'Personality Insights III', 'Personality Insights IV', 'Personality Insights V']; 18 | 19 | export const toneTitles = ['Emotional Tone Insights I', 'Emotional Tone Insights II', 'Language Tone Insights', 'Social Tone Insights I', 'Social Tone Insights II']; 20 | 21 | export const barDomainCoords = [ 22 | {x: [0, 100], y: [35, 48]}, 23 | {x: [0, 100], y: [24, 36]}, 24 | {x: [0, 140], y: [12, 26]}, 25 | {x: [0, 160], y: [0, 14]}, 26 | {x: [0, 150], y: [0, 14]} //toneAnalysis 27 | ]; 28 | 29 | export const barGraphTitles = ['Personality Insights I', 'Personality Insights II', 'Personality Insights III', 'Personality Insights IV', 'Tone Analysis']; 30 | 31 | export const personalityDataRange = [`35-47`, `24-35`, `12-24`, `0-12`]; 32 | 33 | //line graph helper 34 | export const filterTraits = (arr) => { 35 | const traits = ['Imagination', 'Self-discipline', 'Cheerfulness', 'Outgoing', 'Altruism', 'Modesty', 'Trust', 'Self-consciousness', 'Curiosity', 'Harmony', 'Love', 'Openness to change', 'Susceptible to stress', 'Stability', 'Intellect']; 36 | return arr.filter(obj => { 37 | return traits.includes(obj.key); 38 | }); 39 | }; 40 | 41 | //bar graph helper 42 | export const mapLabels = (arr) => { 43 | return arr.map(obj => obj.quality + ` ${(obj.score * 100).toFixed(1)}%`); 44 | }; 45 | 46 | export const sortData = (arr) => { 47 | let count = 1; 48 | return arr.sort((a, b) => b.score - a.score).map(obj => { 49 | return { 50 | x: count++, 51 | y: obj.score * 100 52 | }; 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /src/native/utils/dataList.js: -------------------------------------------------------------------------------- 1 | 2 | const occupation = ['Select', 'Sales', 'Hospitality', 'Healthcare', 'Custodial', 'Accounting', 'Teaching', 'Law-Enforcement', 'Law', 'Finance', 'Engineering', 'Administration', 'Student', 'Other']; 3 | 4 | const income = ['Select', 'Under-$15,000', '$15,000-to-$24,999', '$25,000-to-$34,999', '$35,000-to-$49,999', '$50,000-to-$74,999', '$75,000-to-$99,999', '$100,000-to-$149,999', '$150,000-to-$199,999', '$200,000-and-over']; 5 | 6 | const ethnicity = ['Select', 'White', 'Black', 'Hispanic', 'Asian', 'American-Indian/Alaska-Native', 'Hawaiian/Other-Pacific-Islander', 'Other']; 7 | 8 | const religion = ['Select', 'Protestant', 'Catholic', 'Mormon', 'Judaism', 'Islam', 'Buddhism', 'Hinduism', 'Other', 'Unaffiliated']; 9 | 10 | const education = ['Select', 'High-School', 'Some-College', 'Associate-Degree', 'Bachelor-Degree', 'Advanced-Degree']; 11 | 12 | const maritalStatus = ['Select', 'Single', 'Married', 'Widowed', 'Divorced']; 13 | 14 | export { occupation, income, ethnicity, religion, education, maritalStatus }; 15 | -------------------------------------------------------------------------------- /src/native/utils/validation.js: -------------------------------------------------------------------------------- 1 | //Check valid email 2 | export const checkEmail =(email) => { 3 | let regexEmail = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 4 | return regexEmail.test(email) 5 | } 6 | -------------------------------------------------------------------------------- /src/web/app.web.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {Router, Route, browserHistory} from 'react-router'; 3 | 4 | import TopLevelComponent from './screens/TopLevelComponent.web'; 5 | 6 | export default class App extends Component { 7 | 8 | 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | ) 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/web/screens/TopLevelComponent.web.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | Dimensions 7 | } from 'react-native'; 8 | let {height, width} = Dimensions.get('window'); 9 | 10 | 11 | export default class Screen1 extends Component { 12 | constructor(props, context) { 13 | super(props, context); 14 | 15 | } 16 | render() { 17 | 18 | return ( 19 | 20 | 21 | This is the top level component of this app. 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | const styles = StyleSheet.create({ 29 | container: { 30 | width: width, 31 | height: height, 32 | justifyContent: 'center', 33 | alignItems: 'center', 34 | backgroundColor: '#F5FCFF', 35 | } 36 | }); 37 | 38 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | var NODE_ENV = process.env.NODE_ENV; 5 | var ROOT_PATH = path.resolve(__dirname); 6 | 7 | module.exports = { 8 | entry: { 9 | main: './index.web.js', 10 | }, 11 | node: { 12 | __dirname: true 13 | }, 14 | 15 | module: { 16 | loaders: [ 17 | 18 | { 19 | test: /\.js?$/, 20 | exclude: /node_modules/, 21 | loader: 'babel', 22 | query: { 23 | plugins: ['transform-runtime'], 24 | presets: ['es2015', 'stage-0', 'react'], 25 | }, 26 | }, 27 | { 28 | test: /\.css$/, 29 | loader: 'style-loader!css-loader' 30 | }, 31 | { 32 | test : /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9-=&.]+)?$/, 33 | loader : 'file-loader', 34 | include: path.resolve(__dirname, "node_modules/react-native-vector-icons"), 35 | }, 36 | { 37 | test: /\.(jpe?g|png|gif|svg)$/i, 38 | loader: "file-loader"}, 39 | ], 40 | }, 41 | resolve: { 42 | alias: { 43 | 'react-native': 'react-native-web', 44 | }, 45 | }, 46 | devServer: { 47 | historyApiFallback: true, 48 | inline:true, 49 | port: 9000 50 | }, 51 | }; -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | let NODE_ENV = process.env.NODE_ENV; 4 | let ROOT_PATH = path.resolve(__dirname); 5 | 6 | 7 | export default { 8 | devtool: 'source-map', 9 | 10 | entry: { 11 | main: './index.web.js', 12 | }, 13 | node: { 14 | __dirname: true 15 | }, 16 | output: { 17 | path: path.join(__dirname, 'public'), 18 | filename: 'bundle.js', 19 | publicPath: '/public/' 20 | }, 21 | resolve: { 22 | alias: { 23 | 'react-native': 'react-native-web', 24 | }, 25 | }, 26 | 27 | plugins: [ 28 | new webpack.optimize.DedupePlugin(), 29 | new webpack.optimize.UglifyJsPlugin({ 30 | minimize: true, 31 | compress: { 32 | warnings: false 33 | } 34 | }), 35 | new webpack.DefinePlugin({ 36 | 'process.env': { 37 | 'NODE_ENV': JSON.stringify('production') 38 | } 39 | }) 40 | ], 41 | 42 | module: { 43 | loaders: [ 44 | { 45 | test: /\.scss?$/, 46 | loader: 'style!css!sass', 47 | include: path.join(__dirname, 'src', 'styles') 48 | }, 49 | { 50 | test: /\.js?$/, 51 | exclude: /node_modules/, 52 | loader: 'babel', 53 | query: { 54 | plugins: ['transform-runtime'], 55 | presets: ['es2015', 'stage-0', 'react'], 56 | }, 57 | }, 58 | { 59 | test: /\.css$/, 60 | loader: 'style-loader!css-loader' 61 | }, 62 | { 63 | test: /\.(jpe?g|png|gif|svg)$/i, 64 | loader: "file-loader" 65 | }, 66 | ] 67 | } 68 | } --------------------------------------------------------------------------------