├── .all-contributorsrc ├── .circleci └── config.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── images └── ios-release-build-error.png ├── package.json ├── template.config.js ├── template ├── .buckconfig ├── .d.ts ├── .detoxrc.json ├── .eslintignore ├── .eslintrc.js ├── .github │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .node-version ├── .prettierrc ├── .ruby-version ├── .solidarity ├── .vscode │ └── settings.json ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── README.md ├── __mocks__ │ └── react-native-splash-screen.js ├── _templates │ ├── component │ │ └── new │ │ │ ├── component.ejs │ │ │ ├── export.ejs │ │ │ ├── inject_story.ejs │ │ │ └── stories.ejs │ ├── e2e │ │ └── new │ │ │ └── spec.ejs │ ├── screen │ │ └── new │ │ │ ├── component.ejs │ │ │ ├── export.ejs │ │ │ └── prompt.js │ ├── setup │ │ └── splashscreen │ │ │ ├── SplashIcon.imageset │ │ │ ├── Contents.json │ │ │ ├── launch_screen.png │ │ │ ├── launch_screen@2x.png │ │ │ └── launch_screen@3x.png │ │ │ ├── android │ │ │ ├── MainActivity.ejs.t │ │ │ ├── MainActivityImport1.ejs.t │ │ │ ├── MainActivityImport2.ejs.t │ │ │ ├── colors.xml.ejs.t │ │ │ ├── copyImagesToMipMaps.ejs.t │ │ │ ├── disableWindowPreview.ejs.t │ │ │ ├── launch_screen.xml.ejs.t │ │ │ └── styles.xml.ejs.t │ │ │ ├── ios │ │ │ ├── AppDelegate1.ejs.t │ │ │ ├── AppDelegate2.ejs.t │ │ │ ├── LaunchScreen.xib.ejs.t │ │ │ └── copySplashIconImageset.ejs.t │ │ │ ├── launch_screen.png │ │ │ ├── launch_screen@2x.png │ │ │ └── launch_screen@3x.png │ └── util │ │ └── new │ │ ├── index.ejs.t │ │ ├── test.ejs.t │ │ └── util.ejs.t ├── _watchmanconfig ├── android │ ├── app │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── helloworld │ │ │ │ └── DetoxTest.java │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── helloworld │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── helloworld │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── drawable │ │ │ └── bootsplash.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── network_security_config.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── docs │ ├── circle-ci.md │ ├── hygen-templates.md │ ├── navigation.md │ └── splashscreens.md ├── e2e │ ├── config.json │ ├── init.js │ └── introScreen.spec.js ├── fastlane │ ├── Fastfile │ ├── Pluginfile │ ├── README.md │ └── metadata │ │ ├── app_icon.png │ │ └── app_icon_android.png ├── husky.config.js ├── index.js ├── ios │ ├── Dummy.swift │ ├── Gemfile │ ├── HelloWorld-Bridging-Header.h │ ├── HelloWorld.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── HelloWorld.xcscheme │ ├── HelloWorld │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ ├── HelloWorldTests │ │ ├── HelloWorldTests.m │ │ └── Info.plist │ └── Podfile ├── metro.config.js ├── package.json ├── react-native.config.js ├── rn-cli.config.js ├── setup │ └── index.js ├── splashscreenPreview │ └── SplashScreens-iPhone12.gif ├── src │ ├── App.tsx │ ├── assets │ │ ├── fonts │ │ │ ├── Archivo-Bold.ttf │ │ │ ├── Archivo-BoldItalic.ttf │ │ │ ├── Archivo-Italic.ttf │ │ │ ├── Archivo-Medium.ttf │ │ │ ├── Archivo-MediumItalic.ttf │ │ │ ├── Archivo-Regular.ttf │ │ │ ├── Archivo-SemiBold.ttf │ │ │ ├── Archivo-SemiBoldItalic.ttf │ │ │ ├── Blockletter.otf │ │ │ └── README.md │ │ └── images │ │ │ ├── background.png │ │ │ ├── background@2x.png │ │ │ └── background@3x.png │ ├── components │ │ ├── Button │ │ │ ├── Button.stories.tsx │ │ │ ├── Button.tsx │ │ │ └── index.ts │ │ ├── Container │ │ │ ├── Container.stories.tsx │ │ │ ├── Container.tsx │ │ │ └── index.ts │ │ ├── Login │ │ │ ├── Login.stories.tsx │ │ │ ├── Login.tsx │ │ │ └── index.ts │ │ ├── Registration │ │ │ ├── Registration.stories.tsx │ │ │ ├── Registration.tsx │ │ │ └── index.ts │ │ ├── Screen │ │ │ ├── Screen.stories.tsx │ │ │ ├── Screen.tsx │ │ │ └── index.ts │ │ ├── Text │ │ │ ├── Text.stories.tsx │ │ │ ├── Text.tsx │ │ │ └── index.ts │ │ ├── TextInput │ │ │ ├── TextInput.stories.tsx │ │ │ ├── TextInput.tsx │ │ │ └── index.ts │ │ └── Touchable │ │ │ ├── Touchable.stories.tsx │ │ │ ├── Touchable.tsx │ │ │ └── index.ts │ ├── navigation │ │ ├── AppNav.tsx │ │ ├── GuestNav.tsx │ │ ├── MainNav.tsx │ │ ├── OnboardingNav.tsx │ │ └── createFakeScreen.tsx │ ├── screens │ │ ├── IntroScreen │ │ │ ├── IntroScreen.tsx │ │ │ └── index.ts │ │ ├── LoginScreen │ │ │ ├── LoginScreen.tsx │ │ │ └── index.ts │ │ └── RegistrationScreen │ │ │ ├── RegistrationScreen.tsx │ │ │ └── index.ts │ ├── styles │ │ ├── colors.ts │ │ ├── fonts.ts │ │ ├── index.ts │ │ ├── margins.ts │ │ └── theme.ts │ ├── types │ │ └── AccessibilityRole.ts │ └── utils │ │ └── trimText │ │ ├── index.ts │ │ ├── trimText.test.ts │ │ └── trimText.ts ├── storybook │ ├── index.js │ ├── rn-addons.js │ ├── stories │ │ └── index.ts │ └── storybook.js └── tsconfig.json └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | 10 | "login": "cmejet", 11 | "name": "Jenn", 12 | "avatar_url": "https://avatars3.githubusercontent.com/u/7119624?v=4", 13 | "profile": "https://github.com/cmejet", 14 | "contributions": [ 15 | "code", 16 | "review" 17 | ], 18 | { 19 | "login": "mcavaliere", 20 | "name": "Mike Cavaliere", 21 | "avatar_url": "https://avatars3.githubusercontent.com/u/147237?v=4", 22 | "profile": "http://mikecavaliere.com/", 23 | "contributions": [ 24 | "code", 25 | "review" 26 | ] 27 | }, 28 | { 29 | "login": "cball", 30 | "name": "Chris Ball", 31 | "avatar_url": "https://avatars1.githubusercontent.com/u/14339?v=4", 32 | "profile": "http://echobind.com", 33 | "contributions": [ 34 | "code", 35 | "review" 36 | ] 37 | }, 38 | { 39 | "login": "rynatk", 40 | "name": "Ryan Atkinson", 41 | "avatar_url": "https://avatars0.githubusercontent.com/u/13787517?v=4", 42 | "profile": "https://www.linkedin.com/in/rynatk/", 43 | "contributions": [ 44 | "code", 45 | "review" 46 | ] 47 | } 48 | ], 49 | "contributorsPerLine": 7, 50 | "projectName": "react-native-template", 51 | "projectOwner": "echobind", 52 | "repoType": "github", 53 | "repoHost": "https://github.com", 54 | "skipCi": true 55 | } 56 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: "circleci/node:latest" 6 | steps: 7 | - checkout 8 | - run: 9 | name: install 10 | command: yarn 11 | - run: 12 | name: release 13 | command: yarn run semantic-release -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | pods/ 25 | 26 | # Android/IntelliJ 27 | # 28 | build/ 29 | .idea 30 | .gradle 31 | local.properties 32 | *.iml 33 | 34 | # node.js 35 | # 36 | node_modules/ 37 | npm-debug.log 38 | yarn-error.log 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | !debug.keystore 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/ 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | */fastlane/report.xml 57 | */fastlane/Preview.html 58 | */fastlane/screenshots 59 | 60 | # Bundle artifact 61 | *.jsbundle 62 | 63 | # CocoaPods 64 | /ios/Pods/ 65 | 66 | # misc 67 | .jest -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - Present Echobind 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `react-native-template` 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) 4 | 5 | 6 |
7 |

8 | 9 | Logo 10 | 11 | 12 |

react-native-template

13 | 14 |

15 | Our Recommended template for React Native projects. 16 |
17 |
18 | Report Bug 19 | · 20 | Request Feature 21 |

22 |

23 |
24 | 25 | number of contributors. 26 | 27 | License. 28 |
29 | 30 |
31 | 32 | ## Table of Contents 33 | 34 | - [Quickstart](#quickstart) 35 | - [About the Project](#about-the-project) 36 | - [Built With](#built-with) 37 | - [Getting Started](#getting-started) 38 | - [Prerequisites](#prerequisites) 39 | - [Setup](#setup) 40 | - [Troubleshooting](#troubleshooting) 41 | - [Usage](#usage) 42 | - [CI/Deployment](#ci--deployment) 43 | - [Docs](#docs) 44 | - [Contributing](#contributing) 45 | - [Publishing New Release](#publish-new-release) 46 | - [Acknowledgements](#acknowledgements) 47 | - [License](#license) 48 | - [Contributors](#contributors) 49 | 50 | ## Quickstart 51 | 52 | To get started with our template, run one of the following commands: 53 | ```shell 54 | # using npx, install our latest version from npm 55 | npx react-native init MyApp --template=@echobind/react-native-template 56 | 57 | # using npx and the github repo directly 58 | npx react-native init MyApp --template=https://github.com/echobind/react-native-template 59 | 60 | # using yarn & the react-native cli 61 | yarn global add react-native-cli 62 | react-native init MyApp --template=https://github.com/echobind/react-native-template 63 | ``` 64 | 65 | If you see an error after installing using the first option, pass the flag `--ignore-existing` and run: 66 | ```shell 67 | npx --ignore-existing react-native init MyApp --template=@echobind/react-native-template 68 | ``` 69 | 70 | ## About The Project 71 | 72 | Here at Echobind, we value developer productivity. After having built lots of React Native projects, we decided to put together our own template to speed up development. Our template includes the following: 73 | 74 | 🏆 Dev Productivity: 75 | 76 | - [Hygen](http://www.hygen.io/) templates to easily generate components, screens, and utils with tests and stories. 77 | - vscode settings for common overrides (🎨 Colors, formatOnSave and rulers width that matches prettier) 78 | - default Fastlane scripts for icon generation 79 | - global styles and colors 80 | - `react-navigation` preconfigured with a common setup 81 | - Pre-configured scripts in `package.json` to start the app & deal with simulators 82 | - Setup `lint-staged` to run eslint checks on `precommit` 83 | - Setup the app for TypeScript 84 | 85 | We hope it saves you as much time as it saves us! 👍 86 | 87 | ### Built With 88 | 89 | - [React Native `0.61.1`](https://github.com/facebook/react-native) 90 | - [TypeScript](https://www.typescriptlang.org/) 91 | - [`react-navigation`](https://reactnavigation.org/) 92 | - [Storybook 4](https://storybook.js.org/) 93 | - [`@emotion/native`](https://github.com/emotion-js/emotion/tree/master/packages/native) for styling 94 | - [Detox](https://github.com/wix/Detox/) for e2e integration testing 95 | 96 | ## Getting Started 97 | 98 | ### Prerequisites 99 | 100 | While not required, we recommend using a version manager for Ruby and Node. Some popular version managers are: 101 | 102 | ** Ruby ** 103 | 104 | - (chruby)[https://github.com/postmodern/chruby] 105 | - (rbenv)[https://github.com/rbenv/rbenv] 106 | 107 | ** Node ** 108 | 109 | - [nodenv](https://github.com/nodenv/nodenv) 110 | - [nvm](https://github.com/nvm-sh/nvm) 111 | 112 | Follow the install docs for the version manager of your choice. 113 | 114 | During the setup proceess, we will automatically check the versions on your machine and prompt you to install anything you're missing. 115 | 116 | ### Usage 117 | 118 | In order to use this template, follow these steps: 119 | 120 | 1. Initialize a new react-native app: `npx react-native init MyApp --template=https://github.com/echobind/react-native-template` 121 | 2. Change directories into your new app: `cd MyApp` 122 | 3. Run the setup script: `node ./setup`. A successful setup will give you the green light: `✅ Setup completed!` 123 | 124 | During the setup process we will do the following: 125 | 126 | - Setup a display name for your app 127 | - Setup a bundle identifier (ex: com.myapp.mobile) 128 | - Use [Solidarity](https://github.com/infinitered/solidarity) to ensure your environment has all expected dependencies installed 129 | - Run `bundle install` and `pod install` so you don't have to 130 | - Setup placeholder icon and a splash screen 131 | - Setup the first integration test which can be run with the scripts from your package.json with `yarn e2e:ios-debug` or `yarn e2e:android-debug` (android emulator must be setup and open) 132 | 133 | ## Troubleshooting 134 | 135 | If you get an error with an iOS Release build for `ios/Pods/OpenSSL-Universal/ios/lib/libcrypto.a(cryptlib.o)` You should be able to resolve by updating the build settings 136 | ![image](images/ios-release-build-error.png) 137 | 138 | 139 | ## Template Preview 140 | on an iPhone 12: 141 | 142 | iphone12 splash screen preview 143 | 144 | ## CI / Deployment: 145 | 146 | In order to set up CI/Deployment, we've created custom hygen templates to save you time. These live in our [`hygen-templates-echobind` repository](https://github.com/echobind/hygen-echobind-templates). You'll find installation instructions, which will allow you to set up the following: 147 | 148 | - CircleCI preconfigured for React Native. Fast build times! 149 | - Fastlane lanes for alpha, beta, and production releases. These should be run on CI only! 150 | - AppCenter integration for easy alpha distribution 151 | 152 | After installing those, head into the "Setup CircleCI" docs in [`./docs/circle-ci.md`](./template/docs/circle-ci.md), which will walk you through the installation. 153 | 154 | For more info, please follow the [instructions](https://github.com/echobind/hygen-echobind-templates) in the `hygen-templates-echobind` repo. 155 | 156 | ## Docs 157 | 158 | - [Customize Generator Templates](./template/docs/hygen-templates.md) 159 | - [Navigation](./template/docs/navigation.md) 160 | - [Splash Screens](./template/docs/splashscreens.md) 161 | - [Setup CircleCI](./template/docs/circle-ci.md) 162 | 163 | ## Contributing 164 | 165 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 166 | 167 | 1. Fork the Project 168 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 169 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) 170 | 4. Push to the Branch (`git push origin feature/AmazingFeature`) 171 | 5. Open a Pull Request 172 | 173 | ## Publish New Release 174 | 175 | This template is available on npm at [`@echobind/react-native-template`](https://www.npmjs.com/package/@echobind/react-native-template). In order to publish a new release, please follow this process: 176 | 177 | ### Prerequisites 178 | 179 | 1. You must be an Echobind employee 180 | 2. You must have an [npm registry account](https://www.npmjs.com/signup) 181 | 2. You must be a member of the @echobind organization on npm 182 | 183 | ### Create a New Release 184 | 185 | This is handled by `semantic-release` and CircleCI. When a commit is merged into `master`, it analyzes it, then runs a new release based on the type of commit (i.e fix is a patch whereas feat is considered a minor or feature relase). 186 | 187 | ## Acknowledgements 188 | 189 | We'd like to thank the internal team for making this template, and the following organizations: 190 | 191 | - React Native Team 192 | - React Native Community 193 | - [Img Shields](https://shields.io) 194 | 195 | 196 | ## License 197 | 198 | The Echobind React Native template is open source software [licensed as MIT](./LICENSE.md). 199 | 200 | 201 | ## Contributors ✨ 202 | 203 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 |

Mike Cavaliere

💻 👀

Jenn

💻 👀

Chris Ball

💻 👀

Ryan Atkinson

💻 👀
215 | 216 | 217 | 218 | 219 | 220 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 221 | -------------------------------------------------------------------------------- /images/ios-release-build-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/images/ios-release-build-error.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@echobind/react-native-template", 3 | "version": "0.4.0", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "scripts": { 8 | "postpublish": "git push --tags", 9 | "semantic-release": "semantic-release" 10 | }, 11 | "devDependencies": { 12 | "@semantic-release/commit-analyzer": "^8.0.1", 13 | "@semantic-release/git": "^9.0.0", 14 | "@semantic-release/github": "^7.0.0", 15 | "@semantic-release/npm": "^7.0.5", 16 | "@semantic-release/release-notes-generator": "^7.3.2", 17 | "semantic-release": "^17.2.3" 18 | }, 19 | "release": { 20 | "plugins": [ 21 | "@semantic-release/npm", 22 | [ 23 | "@semantic-release/git", 24 | { 25 | "assets": [ 26 | "package.json" 27 | ], 28 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 29 | } 30 | ], 31 | "@semantic-release/github", 32 | [ 33 | "@semantic-release/commit-analyzer", 34 | { 35 | "preset": "angular", 36 | "parserOpts": { 37 | "noteKeywords": [ 38 | "BREAKING CHANGE", 39 | "BREAKING CHANGES", 40 | "BREAKING" 41 | ] 42 | } 43 | } 44 | ], 45 | [ 46 | "@semantic-release/release-notes-generator", 47 | { 48 | "preset": "angular", 49 | "parserOpts": { 50 | "noteKeywords": [ 51 | "BREAKING CHANGE", 52 | "BREAKING CHANGES", 53 | "BREAKING" 54 | ] 55 | }, 56 | "writerOpts": { 57 | "commitsSort": [ 58 | "subject", 59 | "scope" 60 | ] 61 | } 62 | } 63 | ] 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /template.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | placeholderName: "HelloWorld", 3 | titlePlaceholder: "Hello World", 4 | templateDir: "./template" 5 | }; 6 | -------------------------------------------------------------------------------- /template/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /template/.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '.jpg'; 3 | declare module '*.json'; -------------------------------------------------------------------------------- /template/.detoxrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "testRunner": "jest", 3 | "runnerConfig": "e2e/config.json", 4 | "configurations": { 5 | "ios.sim.debug": { 6 | "type": "ios.simulator", 7 | "build": "xcodebuild -workspace ios/HelloWorld.xcworkspace -configuration Debug -scheme HelloWorld -destination name='iPhone 11' -derivedDataPath ios/build", 8 | "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/HelloWorld.app", 9 | "device": { 10 | "type": "iPhone 11" 11 | } 12 | }, 13 | "ios.sim.release": { 14 | "type": "ios.simulator", 15 | "build": "xcodebuild -workspace ios/HelloWorld.xcworkspace -configuration Release -scheme HelloWorld -destination name='iPhone 11' -derivedDataPath ios/build", 16 | "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/HelloWorld.app", 17 | "device": { 18 | "type": "iPhone 11" 19 | } 20 | }, 21 | "android.emu.debug": { 22 | "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk", 23 | "build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..", 24 | "type": "android.emulator", 25 | "device": { 26 | "avdName": "Pixel_3_API_29" 27 | } 28 | }, 29 | "android.emu.release": { 30 | "binaryPath": "android/app/build/outputs/apk/release/app-release.apk", 31 | "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..", 32 | "type": "android.emulator", 33 | "device": { 34 | "avdName": "Pixel_3_API_29" 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /template/.eslintignore: -------------------------------------------------------------------------------- 1 | d.ts 2 | **/*.test* 3 | **/*stories.ts -------------------------------------------------------------------------------- /template/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['plugin:echobind/react-native'], 4 | }; 5 | -------------------------------------------------------------------------------- /template/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Overview / Description 2 | 3 | ## Changes 4 | - Change 1 5 | - Change 2 6 | 7 | ## Screenshots 8 | (prefer animated gif) 9 | 10 | ## Checklist 11 | - [ ] Automated tests 12 | - [ ] Creating a new project still works 13 | - [ ] Added docs 14 | 15 | Fixes #xx 16 | -------------------------------------------------------------------------------- /template/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # OSX 15 | # 16 | .DS_Store 17 | 18 | # Xcode 19 | # 20 | build/ 21 | pods/ 22 | *.pbxuser 23 | !default.pbxuser 24 | *.mode1v3 25 | !default.mode1v3 26 | *.mode2v3 27 | !default.mode2v3 28 | *.perspectivev3 29 | !default.perspectivev3 30 | xcuserdata 31 | *.xccheckout 32 | *.moved-aside 33 | DerivedData 34 | *.hmap 35 | *.ipa 36 | *.xcuserstate 37 | project.xcworkspace 38 | 39 | # Android/IntelliJ 40 | # 41 | build/ 42 | .idea 43 | .gradle 44 | local.properties 45 | *.iml 46 | .project 47 | android/.settings 48 | android/app/.settings/ 49 | android/app/.classpath 50 | android/.gradle 51 | android/app/build 52 | *.keystore 53 | 54 | # Directory for instrumented libs generated by jscoverage/JSCover 55 | lib-cov 56 | 57 | # Coverage directory used by tools like istanbul 58 | coverage 59 | 60 | # nyc test coverage 61 | .nyc_output 62 | 63 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 64 | .grunt 65 | 66 | # Bower dependency directory (https://bower.io/) 67 | bower_components 68 | 69 | # node-waf configuration 70 | .lock-wscript 71 | 72 | # Compiled binary addons (https://nodejs.org/api/addons.html) 73 | build/Release 74 | 75 | # Dependency directories 76 | node_modules/ 77 | jspm_packages/ 78 | 79 | # TypeScript v1 declaration files 80 | typings/ 81 | 82 | # Optional npm cache directory 83 | .npm 84 | 85 | # Optional eslint cache 86 | .eslintcache 87 | 88 | # Optional REPL history 89 | .node_repl_history 90 | 91 | # Output of 'npm pack' 92 | *.tgz 93 | 94 | # Yarn Integrity file 95 | .yarn-integrity 96 | 97 | # ignore all env files except example 98 | .env* 99 | !env.example 100 | 101 | # ios build output 102 | ios/build 103 | *.p12 104 | *.pem 105 | *.pkey 106 | *.dSYM.* 107 | report.xml 108 | 109 | .jest/cache 110 | -------------------------------------------------------------------------------- /template/.node-version: -------------------------------------------------------------------------------- 1 | 10.16.0 2 | -------------------------------------------------------------------------------- /template/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "printWidth": 100 5 | } 6 | -------------------------------------------------------------------------------- /template/.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-2.6.5 2 | -------------------------------------------------------------------------------- /template/.solidarity: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/solidaritySchema", 3 | "requirements": { 4 | "Node": [ 5 | { 6 | "rule": "cli", 7 | "binary": "node", 8 | "semver": ">=10.16.0" 9 | } 10 | ], 11 | "Yarn": [ 12 | { 13 | "rule": "cli", 14 | "binary": "yarn", 15 | "version": "--version", 16 | "semver": ">=1.17.3" 17 | } 18 | ], 19 | "Cocoapods and Fastlane": [ 20 | { 21 | "rule": "cli", 22 | "binary": "ruby", 23 | "semver": ">=2.0.0", 24 | "error": "Ruby is required to run Cocoapods and Fastlane. We recommend installing Ruby with a version manager (https://github.com/echobind/react-native-template-echobind#prerequisites)" 25 | }, 26 | { 27 | "rule": "cli", 28 | "binary": "bundle", 29 | "version": "version", 30 | "semver": ">=2.0.2", 31 | "error": "Bundler is used to install RubyGems" 32 | }, 33 | { 34 | "rule": "cli", 35 | "binary": "pod", 36 | "semver": ">=1.7.0", 37 | "error": "Cocopods is required to be installed as of React Native 0.60" 38 | }, 39 | { 40 | "rule": "cli", 41 | "binary": "gm", 42 | "error": "GraphicsMagick is needed to generate icons and splashscreens. Please run 'brew install graphicsmagick'", 43 | } 44 | ], 45 | "Android": [ 46 | { 47 | "rule": "cli", 48 | "binary": "emulator" 49 | }, 50 | { 51 | "rule": "cli", 52 | "binary": "android" 53 | }, 54 | { 55 | "rule": "env", 56 | "variable": "ANDROID_HOME", 57 | "error": "The ANDROID_HOME environment variable must be set to your local SDK. (https://facebook.github.io/react-native/docs/getting-started)" 58 | } 59 | ], 60 | "Watchman": [ 61 | { 62 | "rule": "cli", 63 | "binary": "watchman", 64 | "error": "Please install watchman on this machine. (https://facebook.github.io/watchman/docs/install.html#buildinstall)", 65 | "platform": [ 66 | "darwin", 67 | "linux" 68 | ] 69 | } 70 | ], 71 | "React Native": [ 72 | { 73 | "rule": "shell", 74 | "command": "which react-native", 75 | "match": "node_modules/.bin/react-native", 76 | "error": "It looks like you have react-native-cli installed globally. Use 'yarn global remove react-native' or 'npm uninstall -g react-native'. See: 'https://github.com/react-native-community/cli#about'" 77 | } 78 | ], 79 | "Detox": [ 80 | { 81 | "rule": "cli", 82 | "binary": "applesimutils", 83 | "semver": ">=0.7.4", 84 | "error": "To install, use 'yarn solidarity --fix'. To upgrade, use 'brew upgrade applesimutils'. If you get errors, try 'brew untap wix/brew && brew tap wix/brew'", 85 | "fix": "brew tap wix/brew && brew install applesimutils" 86 | } 87 | ], 88 | "Xcode": [ 89 | { 90 | "rule": "cli", 91 | "binary": "xcodebuild", 92 | "semver": ">=10.2", 93 | "platform": "darwin", 94 | "error": "XCode {{wantedVersion}} is required (you have {{installedVersion}}). Please download from https://developer.apple.com/download/more" 95 | }, 96 | { 97 | "rule": "cli", 98 | "binary": "xcrun", 99 | "semver": ">=43.0", 100 | "platform": "darwin", 101 | "error": "XCode developer tools {{wantedVersion}} is required (you have {{installedVersion}}). Please download from https://developer.apple.com/download/more" 102 | } 103 | ], 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /template/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "titleBar.activeForeground": "#29323F", 4 | "titleBar.inactiveForeground": "#29323F", 5 | "titleBar.activeBackground": "#8CCBDF", 6 | "titleBar.inactiveBackground": "#8CCBDF" 7 | }, 8 | "editor.formatOnSave": true, 9 | "editor.rulers": [100], 10 | "eslint.autoFixOnSave": true, 11 | "prettier.trailingComma": "all", 12 | "eslint.validate": [ 13 | "javascript", 14 | "javascriptreact", 15 | { "language": "typescript", "autoFix": true }, 16 | { "language": "typescriptreact", "autoFix": true } 17 | ], 18 | "[javascript]": { 19 | "editor.formatOnSave": true 20 | }, 21 | "[javascriptreact]": { 22 | "editor.formatOnSave": true 23 | }, 24 | "[typescript]": { 25 | "editor.formatOnSave": true 26 | }, 27 | "[typescriptreact]": { 28 | "editor.formatOnSave": true 29 | }, 30 | "editor.codeActionsOnSave": { 31 | "source.fixAll.eslint": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /template/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /template/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 6 | 7 | gem "fastlane" 8 | plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') 9 | eval_gemfile(plugins_path) if File.exist?(plugins_path) 10 | -------------------------------------------------------------------------------- /template/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.1) 5 | addressable (2.7.0) 6 | public_suffix (>= 2.0.2, < 5.0) 7 | atomos (0.1.3) 8 | babosa (1.0.3) 9 | claide (1.0.3) 10 | colored (1.2) 11 | colored2 (3.1.2) 12 | commander-fastlane (4.4.6) 13 | highline (~> 1.7.2) 14 | declarative (0.0.10) 15 | declarative-option (0.1.0) 16 | digest-crc (0.4.1) 17 | domain_name (0.5.20190701) 18 | unf (>= 0.0.5, < 1.0.0) 19 | dotenv (2.7.5) 20 | emoji_regex (1.0.1) 21 | excon (0.72.0) 22 | faraday (0.17.0) 23 | multipart-post (>= 1.2, < 3) 24 | faraday-cookie_jar (0.0.6) 25 | faraday (>= 0.7.4) 26 | http-cookie (~> 1.0.0) 27 | faraday_middleware (0.13.1) 28 | faraday (>= 0.7.4, < 1.0) 29 | fastimage (2.1.7) 30 | fastlane (2.134.0) 31 | CFPropertyList (>= 2.3, < 4.0.0) 32 | addressable (>= 2.3, < 3.0.0) 33 | babosa (>= 1.0.2, < 2.0.0) 34 | bundler (>= 1.12.0, < 3.0.0) 35 | colored 36 | commander-fastlane (>= 4.4.6, < 5.0.0) 37 | dotenv (>= 2.1.1, < 3.0.0) 38 | emoji_regex (>= 0.1, < 2.0) 39 | excon (>= 0.45.0, < 1.0.0) 40 | faraday (~> 0.17) 41 | faraday-cookie_jar (~> 0.0.6) 42 | faraday_middleware (~> 0.13.1) 43 | fastimage (>= 2.1.0, < 3.0.0) 44 | gh_inspector (>= 1.1.2, < 2.0.0) 45 | google-api-client (>= 0.21.2, < 0.24.0) 46 | google-cloud-storage (>= 1.15.0, < 2.0.0) 47 | highline (>= 1.7.2, < 2.0.0) 48 | json (< 3.0.0) 49 | jwt (~> 2.1.0) 50 | mini_magick (>= 4.9.4, < 5.0.0) 51 | multi_xml (~> 0.5) 52 | multipart-post (~> 2.0.0) 53 | plist (>= 3.1.0, < 4.0.0) 54 | public_suffix (~> 2.0.0) 55 | rubyzip (>= 1.3.0, < 2.0.0) 56 | security (= 0.1.3) 57 | simctl (~> 1.6.3) 58 | slack-notifier (>= 2.0.0, < 3.0.0) 59 | terminal-notifier (>= 2.0.0, < 3.0.0) 60 | terminal-table (>= 1.4.5, < 2.0.0) 61 | tty-screen (>= 0.6.3, < 1.0.0) 62 | tty-spinner (>= 0.8.0, < 1.0.0) 63 | word_wrap (~> 1.0.0) 64 | xcodeproj (>= 1.8.1, < 2.0.0) 65 | xcpretty (~> 0.3.0) 66 | xcpretty-travis-formatter (>= 0.0.3) 67 | fastlane-plugin-appicon (0.14.1) 68 | json 69 | mini_magick (>= 4.9.4, < 5.0.0) 70 | gh_inspector (1.1.3) 71 | google-api-client (0.23.9) 72 | addressable (~> 2.5, >= 2.5.1) 73 | googleauth (>= 0.5, < 0.7.0) 74 | httpclient (>= 2.8.1, < 3.0) 75 | mime-types (~> 3.0) 76 | representable (~> 3.0) 77 | retriable (>= 2.0, < 4.0) 78 | signet (~> 0.9) 79 | google-cloud-core (1.3.2) 80 | google-cloud-env (~> 1.0) 81 | google-cloud-env (1.2.1) 82 | faraday (~> 0.11) 83 | google-cloud-storage (1.16.0) 84 | digest-crc (~> 0.4) 85 | google-api-client (~> 0.23) 86 | google-cloud-core (~> 1.2) 87 | googleauth (>= 0.6.2, < 0.10.0) 88 | googleauth (0.6.7) 89 | faraday (~> 0.12) 90 | jwt (>= 1.4, < 3.0) 91 | memoist (~> 0.16) 92 | multi_json (~> 1.11) 93 | os (>= 0.9, < 2.0) 94 | signet (~> 0.7) 95 | highline (1.7.10) 96 | http-cookie (1.0.3) 97 | domain_name (~> 0.5) 98 | httpclient (2.8.3) 99 | json (2.2.0) 100 | jwt (2.1.0) 101 | memoist (0.16.0) 102 | mime-types (3.3) 103 | mime-types-data (~> 3.2015) 104 | mime-types-data (3.2019.1009) 105 | mini_magick (4.9.5) 106 | multi_json (1.14.1) 107 | multi_xml (0.6.0) 108 | multipart-post (2.0.0) 109 | nanaimo (0.2.6) 110 | naturally (2.2.0) 111 | os (1.0.1) 112 | plist (3.5.0) 113 | public_suffix (2.0.5) 114 | representable (3.0.4) 115 | declarative (< 0.1.0) 116 | declarative-option (< 0.2.0) 117 | uber (< 0.2.0) 118 | retriable (3.1.2) 119 | rouge (2.0.7) 120 | rubyzip (1.3.0) 121 | security (0.1.3) 122 | signet (0.11.0) 123 | addressable (~> 2.3) 124 | faraday (~> 0.9) 125 | jwt (>= 1.5, < 3.0) 126 | multi_json (~> 1.10) 127 | simctl (1.6.6) 128 | CFPropertyList 129 | naturally 130 | slack-notifier (2.3.2) 131 | terminal-notifier (2.0.0) 132 | terminal-table (1.8.0) 133 | unicode-display_width (~> 1.1, >= 1.1.1) 134 | tty-cursor (0.7.0) 135 | tty-screen (0.7.0) 136 | tty-spinner (0.9.1) 137 | tty-cursor (~> 0.7) 138 | uber (0.1.0) 139 | unf (0.1.4) 140 | unf_ext 141 | unf_ext (0.0.7.6) 142 | unicode-display_width (1.6.0) 143 | word_wrap (1.0.0) 144 | xcodeproj (1.13.0) 145 | CFPropertyList (>= 2.3.3, < 4.0) 146 | atomos (~> 0.1.3) 147 | claide (>= 1.0.2, < 2.0) 148 | colored2 (~> 3.1) 149 | nanaimo (~> 0.2.6) 150 | xcpretty (0.3.0) 151 | rouge (~> 2.0.7) 152 | xcpretty-travis-formatter (1.0.0) 153 | xcpretty (~> 0.2, >= 0.0.7) 154 | 155 | PLATFORMS 156 | ruby 157 | 158 | DEPENDENCIES 159 | fastlane 160 | fastlane-plugin-appicon 161 | 162 | BUNDLED WITH 163 | 2.0.2 164 | -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | # React Native Project Title 2 | 3 | One Paragraph of project description goes here 4 | 5 | ## Table of Contents 6 | 7 | - [Getting Started](getting-started) 8 | - [Prerequisites](prerequisites) 9 | - [Installing](installing) 10 | - [Develop for Accessibility](develop-for-accessibility) 11 | - [Running The Tests](running-the-tests) 12 | - [E2E Tests](e2e-tests) 13 | - [Deployment](deployment) 14 | - [Built With](built-with) 15 | 16 | 17 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the app to the respective app stores. 18 | 19 | ### Prerequisites 20 | 21 | In order to get this project running locally, please make sure you ahve followed the "React Native CLI Quickstart" in the [React Native "Getting Started"](https://facebook.github.io/react-native/docs/getting-started) guide. 22 | 23 | ### Installing 24 | 25 | To get the app running locally, please follow these steps: 26 | 27 | 1. From the root, install the JavaScript dependencies: 28 | 29 | ```sh 30 | yarn install 31 | ``` 32 | 33 | 2. Install the iOS dependencies: 34 | 35 | ```sh 36 | cd ios && pod install 37 | ``` 38 | 39 | 2. Start the app on iOS by running: 40 | 41 | ```sh 42 | yarn ios 43 | ``` 44 | 45 | 4. Start the app on Android by running (make sure you have a device running on the emulator): 46 | 47 | ```sh 48 | yarn android 49 | ``` 50 | 51 | If all worked correctly, you should have the app running on both the iOS and Android simulators. 52 | 53 | 54 | ## Develop for Accessibility 55 | 56 | Mobile applications should be developed with accessbility in mind. Some simple steps to take include adding accessbility labels and roles to elements within your screens. Some convience features have been added to the Styled Text and Button component to ensure the ease of use. 57 | 58 | 59 | ## Running the tests 60 | 61 | We use `jest` for testing business logic and functions. To run the test suites, run: 62 | 63 | ```sh 64 | yarn test 65 | ``` 66 | 67 | 68 | ### E2E Tests 69 | 70 | End to End (E2E) tests are for full integration tests, clicks, screen elements, etc. For this we use [Detox](https://github.com/wix/Detox/) 71 | 72 | To run tests you must have the applesimutils installed per the [Getting Started on Detox](https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md). Tests can be run locally for iOS and Android with the following commands: 73 | 74 | ```sh 75 | yarn e2e:ios-debug 76 | yarn e2e:ios 77 | yarn e2e:android-debug 78 | yarn e2e:android 79 | ``` 80 | Each of these will test the platform in either release or debug mode as specified. 81 | 82 | 83 | ## Deployment 84 | 85 | Add additional notes about how to deploy this on a live system 86 | 87 | ## Built With 88 | 89 | - [React Native](https://facebook.github.io/react-native/) - The mobile framework used 90 | - [TypeScript](https://typescriptlang.org/) - Static typing 91 | - [styled-system](https://emotion.sh/) - the system we levarage for styling components 92 | - [Emotion](https://emotion.sh/) - CSS-in-JS (used with `styled-system`) 93 | -------------------------------------------------------------------------------- /template/__mocks__/react-native-splash-screen.js: -------------------------------------------------------------------------------- 1 | export default { 2 | show: jest.fn().mockImplementation(() => { 3 | console.log('show splash screen'); 4 | }), 5 | hide: jest.fn().mockImplementation(() => { 6 | console.log('hide splash screen'); 7 | }), 8 | }; 9 | -------------------------------------------------------------------------------- /template/_templates/component/new/component.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/components/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>.tsx 3 | --- 4 | <% const formattedName = h.inflection.transform(name, ['undasherize', 'classify']) -%> 5 | import React, { FC } from 'react'; 6 | 7 | import { Container } from '../Container'; 8 | 9 | interface Props { 10 | /** prop info */ 11 | cool: boolean; 12 | } 13 | 14 | const DEFAULT_PROPS: Partial = { 15 | cool: true, 16 | } 17 | 18 | /** 19 | * Component docs: what does this component do? 20 | */ 21 | export const <%= formattedName %>: FC = (props = DEFAULT_PROPS) => { 22 | const { children } = props; 23 | 24 | return ( 25 | 26 | {children} 27 | 28 | ); 29 | }; 30 | 31 | export default <%= formattedName %>; 32 | -------------------------------------------------------------------------------- /template/_templates/component/new/export.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/components/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>/index.ts 3 | --- 4 | export * from './<%= h.inflection.transform(name, ['undasherize', 'classify']) %>'; -------------------------------------------------------------------------------- /template/_templates/component/new/inject_story.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: storybook/stories/index.ts 4 | skip_if: components/<%= h.inflection.transform(name, ['undasherize', 'classify']) %> 5 | append: true 6 | --- 7 | <% formattedName = h.inflection.transform(name, ['undasherize', 'classify']) -%> 8 | import '../../src/components/<%= formattedName %>/<%= formattedName %>.stories'; -------------------------------------------------------------------------------- /template/_templates/component/new/stories.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/components/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>.stories.tsx 3 | --- 4 | <% const formattedName = h.inflection.transform(name, ['undasherize', 'classify']) -%> 5 | import { storiesOf } from '@storybook/react-native'; 6 | import React from 'react'; 7 | 8 | import { <%= formattedName %> } from './<%= formattedName %>'; 9 | 10 | storiesOf('components/<%= formattedName %>', module).add('Default', () => ( 11 | <<%= formattedName %> /> 12 | )); 13 | -------------------------------------------------------------------------------- /template/_templates/e2e/new/spec.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: e2e/<%= h.inflection.camelize(name) %>.spec.ts 3 | --- 4 | import { device, expect, element, by } from 'detox'; 5 | 6 | describe('<%= h.inflection.titleize(name) %>', () => { 7 | beforeEach(async () => { 8 | await device.reloadReactNative(); 9 | }); 10 | 11 | describe('on load', () => { 12 | it('shows the expected text', async () => { 13 | await expect(element(by.id('what'))).toExist(); 14 | }); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /template/_templates/screen/new/component.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/screens/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>.tsx 3 | --- 4 | <% const comp = h.inflection.transform(name, ['undasherize', 'classify']) -%> 5 | <% if(componentType === 'Class') { -%> 6 | import React, { Component } from 'react'; 7 | import styled from '@emotion/native'; 8 | 9 | import { Screen } from '../../components/Screen'; 10 | import { Text } from '../../components/Text'; 11 | 12 | interface Props { 13 | /** prop info */ 14 | myProp: string; 15 | } 16 | 17 | interface State { 18 | /** state info */ 19 | myStateValue?: boolean; 20 | } 21 | 22 | const INITIAL_STATE: State = { 23 | myStateValue: true, 24 | }; 25 | 26 | export class <%= comp %> extends Component { 27 | public state = INITIAL_STATE; 28 | 29 | public render() { 30 | return ( 31 | 32 | <%= comp %> Screen 33 | 34 | ); 35 | } 36 | } 37 | <% } else { %> 38 | import React, { FC } from 'react'; 39 | import styled from '@emotion/native'; 40 | 41 | import { Screen } from '../../components/Screen'; 42 | import { Text } from '../../components/Text'; 43 | 44 | interface Props { 45 | /** prop info */ 46 | myProp: string; 47 | } 48 | 49 | export const <%= comp %>: FC = () => { 50 | return ( 51 | 52 | <%= comp %> Screen 53 | 54 | ); 55 | }; 56 | <% } -%> -------------------------------------------------------------------------------- /template/_templates/screen/new/export.ejs: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/screens/<%= h.inflection.transform(name, ['undasherize', 'classify']) %>/index.ts 3 | --- 4 | export * from './<%= h.inflection.transform(name, ['undasherize', 'classify']) %>'; 5 | -------------------------------------------------------------------------------- /template/_templates/screen/new/prompt.js: -------------------------------------------------------------------------------- 1 | // see types of prompts: 2 | // https://github.com/SBoudrias/Inquirer.js#prompt-types 3 | // 4 | // and for examples for prompts: 5 | // https://github.com/SBoudrias/Inquirer.js/tree/master/examples 6 | module.exports = [ 7 | { 8 | type: "list", 9 | name: "componentType", 10 | message: "FC or Class?", 11 | choices: ["FC", "Class"], 12 | default: "FC" 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/SplashIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "launch_screen.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "filename": "launch_screen@2x.png", 11 | "scale": "2x" 12 | }, 13 | { 14 | "idiom": "universal", 15 | "filename": "launch_screen@3x.png", 16 | "scale": "3x" 17 | } 18 | ], 19 | "info": { 20 | "version": 1, 21 | "author": "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen.png -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen@2x.png -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/SplashIcon.imageset/launch_screen@3x.png -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/MainActivity.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: android/app/src/main/java/<%= bundleIdentifer.split('.').join('/').toLowerCase() %>/MainActivity.java 4 | after: public class MainActivity extends ReactActivity 5 | skip_if: protected void onCreate 6 | --- 7 | /** 8 | * Injection for react-native-splashscreen 9 | * see: https://github.com/crazycodeboy/react-native-splash-screen#third-stepplugin-configuration 10 | */ 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | SplashScreen.show(this, R.style.SplashScreenTheme); 14 | super.onCreate(savedInstanceState); 15 | } -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/MainActivityImport1.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: android/app/src/main/java/<%= bundleIdentifer.split('.').join('/').toLowerCase() %>/MainActivity.java 4 | before: import com.facebook.react.ReactActivity; 5 | skip_if: import android.os.Bundle 6 | --- 7 | import android.os.Bundle; -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/MainActivityImport2.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: android/app/src/main/java/<%= bundleIdentifer.split('.').join('/').toLowerCase() %>/MainActivity.java 4 | after: import com.facebook.react.ReactActivity; 5 | skip_if: import org.devio.rn.splashscreen.SplashScreen; 6 | --- 7 | import org.devio.rn.splashscreen.SplashScreen; -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/colors.xml.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: android/app/src/main/res/values/colors.xml 3 | --- 4 | 5 | 6 | #1F2E3D 7 | #1F2E3D 8 | #000000 9 | 10 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/copyImagesToMipMaps.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | sh: "cp <%= cwd %>/_templates/setup/splashscreen/launch_screen.png <%= cwd %>/android/app/src/main/res/mipmap-ldpi/launch_screen.png 3 | && cp <%= cwd %>/_templates/setup/splashscreen/launch_screen@2x.png <%= cwd %>/android/app/src/main/res/mipmap-xhdpi/launch_screen.png 4 | && cp <%= cwd %>/_templates/setup/splashscreen/launch_screen@3x.png <%= cwd %>/android/app/src/main/res/mipmap-xxhdpi/launch_screen.png" 5 | --- -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/disableWindowPreview.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | # This is needed to fix a "flash of white" before the splashscreen is shown 3 | inject: true 4 | to: android/app/src/main/res/values/styles.xml 5 | after: Customize your theme here 6 | skip_if: windowDisablePreview 7 | --- 8 | true -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/launch_screen.xml.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: android/app/src/main/res/layout/launch_screen.xml 3 | --- 4 | 5 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/android/styles.xml.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: android/app/src/main/res/values/styles.xml 4 | before: \<\/resources\> 5 | skip_if: Splash screen theme 6 | --- 7 | 8 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/ios/AppDelegate1.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: ios/<%=displayName%>/AppDelegate.m 4 | after: \#import 5 | skip_if: \#import "RNSplashScreen.h" 6 | --- 7 | #import "RNSplashScreen.h" -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/ios/AppDelegate2.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | inject: true 3 | to: ios/<%=displayName%>/AppDelegate.m 4 | before: return YES; 5 | skip_if: [RNSplashScreen show] 6 | --- 7 | [RNSplashScreen show]; -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/ios/LaunchScreen.xib.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: ios/<%=displayName%>/Base.lproj/LaunchScreen.xib 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/ios/copySplashIconImageset.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | sh: "cp -r <%= cwd %>/_templates/setup/splashscreen/SplashIcon.imageset <%= cwd %>/ios/<%=displayName%>/Images.xcassets/" 3 | --- -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/launch_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/launch_screen.png -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/launch_screen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/launch_screen@2x.png -------------------------------------------------------------------------------- /template/_templates/setup/splashscreen/launch_screen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/_templates/setup/splashscreen/launch_screen@3x.png -------------------------------------------------------------------------------- /template/_templates/util/new/index.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/utils/<%= name %>/index.ts 3 | --- 4 | export { default } from './<%= name %>' 5 | -------------------------------------------------------------------------------- /template/_templates/util/new/test.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/utils/<%= name %>/test.ts 3 | --- 4 | import <%= name %> from './<%= name %>' 5 | 6 | describe('no arguments', () => { 7 | test('returns something expected', () => { 8 | expect(true).toBe(false) 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /template/_templates/util/new/util.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: src/utils/<%= name %>/<%= name %>.ts 3 | --- 4 | const <%= name %> = () => true 5 | 6 | export default <%= name %> 7 | -------------------------------------------------------------------------------- /template/_watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /template/android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.helloworld", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.helloworld", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /template/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 | * // https://reactnative.dev/docs/performance#enable-the-ram-format 22 | * bundleCommand: "ram-bundle", 23 | * 24 | * // whether to bundle JS and assets in debug mode 25 | * bundleInDebug: false, 26 | * 27 | * // whether to bundle JS and assets in release mode 28 | * bundleInRelease: true, 29 | * 30 | * // whether to bundle JS and assets in another build variant (if configured). 31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 32 | * // The configuration property can be in the following formats 33 | * // 'bundleIn${productFlavor}${buildType}' 34 | * // 'bundleIn${buildType}' 35 | * // bundleInFreeDebug: true, 36 | * // bundleInPaidRelease: true, 37 | * // bundleInBeta: true, 38 | * 39 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 40 | * // for example: to disable dev mode in the staging build type (if configured) 41 | * devDisabledInStaging: true, 42 | * // The configuration property can be in the following formats 43 | * // 'devDisabledIn${productFlavor}${buildType}' 44 | * // 'devDisabledIn${buildType}' 45 | * 46 | * // the root of your project, i.e. where "package.json" lives 47 | * root: "../../", 48 | * 49 | * // where to put the JS bundle asset in debug mode 50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 51 | * 52 | * // where to put the JS bundle asset in release mode 53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 54 | * 55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 56 | * // require('./image.png')), in debug mode 57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 58 | * 59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 60 | * // require('./image.png')), in release mode 61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 62 | * 63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 67 | * // for example, you might want to remove it from here. 68 | * inputExcludes: ["android/**", "ios/**"], 69 | * 70 | * // override which node gets called and with what additional arguments 71 | * nodeExecutableAndArgs: ["node"], 72 | * 73 | * // supply additional arguments to the packager 74 | * extraPackagerArgs: [] 75 | * ] 76 | */ 77 | 78 | project.ext.react = [ 79 | entryFile: "index.js", 80 | enableHermes: false, // clean and rebuild if changing 81 | ] 82 | 83 | apply from: "../../node_modules/react-native/react.gradle" 84 | 85 | 86 | project.ext.vectoricons = [ 87 | iconFontNames: [ 'FontAwesome.ttf', 'MaterialIcons.ttf', 'SimpleLineIcons.ttf' ] // Name of the font files you want to copy 88 | ] 89 | 90 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" 91 | 92 | /** 93 | * Set this to true to create two separate APKs instead of one: 94 | * - An APK that only works on ARM devices 95 | * - An APK that only works on x86 devices 96 | * The advantage is the size of the APK is reduced by about 4MB. 97 | * Upload all the APKs to the Play Store and people will download 98 | * the correct one based on the CPU architecture of their device. 99 | */ 100 | def enableSeparateBuildPerCPUArchitecture = false 101 | 102 | /** 103 | * Run Proguard to shrink the Java bytecode in release builds. 104 | */ 105 | def enableProguardInReleaseBuilds = false 106 | 107 | /** 108 | * The preferred build flavor of JavaScriptCore. 109 | * 110 | * For example, to use the international variant, you can use: 111 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 112 | * 113 | * The international variant includes ICU i18n library and necessary data 114 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 115 | * give correct results when using with locales other than en-US. Note that 116 | * this variant is about 6MiB larger per architecture than default. 117 | */ 118 | def jscFlavor = 'org.webkit:android-jsc:+' 119 | 120 | /** 121 | * Whether to enable the Hermes VM. 122 | * 123 | * This should be set on project.ext.react and mirrored here. If it is not set 124 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 125 | * and the benefits of using Hermes will therefore be sharply reduced. 126 | */ 127 | def enableHermes = project.ext.react.get("enableHermes", false); 128 | 129 | android { 130 | compileSdkVersion rootProject.ext.compileSdkVersion 131 | 132 | compileOptions { 133 | sourceCompatibility JavaVersion.VERSION_1_8 134 | targetCompatibility JavaVersion.VERSION_1_8 135 | } 136 | 137 | defaultConfig { 138 | applicationId "com.helloworld" 139 | minSdkVersion rootProject.ext.minSdkVersion 140 | targetSdkVersion rootProject.ext.targetSdkVersion 141 | versionCode 1 142 | versionName "1.0" 143 | testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type 144 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 145 | } 146 | splits { 147 | abi { 148 | reset() 149 | enable enableSeparateBuildPerCPUArchitecture 150 | universalApk false // If true, also generate a universal APK 151 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 152 | } 153 | } 154 | signingConfigs { 155 | debug { 156 | storeFile file('debug.keystore') 157 | storePassword 'android' 158 | keyAlias 'androiddebugkey' 159 | keyPassword 'android' 160 | } 161 | } 162 | buildTypes { 163 | debug { 164 | signingConfig signingConfigs.debug 165 | } 166 | release { 167 | // Caution! In production, you need to generate your own keystore file. 168 | // see https://reactnative.dev/docs/signed-apk-android. 169 | signingConfig signingConfigs.debug 170 | minifyEnabled enableProguardInReleaseBuilds 171 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 172 | } 173 | } 174 | 175 | // applicationVariants are e.g. debug, release 176 | applicationVariants.all { variant -> 177 | variant.outputs.each { output -> 178 | // For each separate APK per architecture, set a unique version code as described here: 179 | // https://developer.android.com/studio/build/configure-apk-splits.html 180 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 181 | def abi = output.getFilter(OutputFile.ABI) 182 | if (abi != null) { // null for the universal-debug, universal-release variants 183 | output.versionCodeOverride = 184 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 185 | } 186 | 187 | } 188 | } 189 | } 190 | 191 | dependencies { 192 | implementation fileTree(dir: "libs", include: ["*.jar"]) 193 | implementation "com.facebook.react:react-native:+" // From node_modules 194 | api 'androidx.annotation:annotation:1.1.0' 195 | androidTestImplementation('com.wix:detox:+') { transitive = true } 196 | androidTestImplementation 'junit:junit:4.12' 197 | //noinspection GradleDynamicVersion 198 | implementation "com.facebook.react:react-native:+" // From node_modules 199 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 200 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { 201 | exclude group:'com.facebook.fbjni' 202 | } 203 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 204 | exclude group:'com.facebook.flipper' 205 | exclude group:'com.squareup.okhttp3', module:'okhttp' 206 | } 207 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { 208 | exclude group:'com.facebook.flipper' 209 | } 210 | if (enableHermes) { 211 | def hermesPath = "../../node_modules/hermes-engine/android/"; 212 | debugImplementation files(hermesPath + "hermes-debug.aar") 213 | releaseImplementation files(hermesPath + "hermes-release.aar") 214 | } else { 215 | implementation jscFlavor 216 | } 217 | } 218 | configurations.all { 219 | resolutionStrategy { 220 | // TODO: Line below required for Detox since version 12.5 221 | // It should removed as soon as the project compiles without it 222 | force 'androidx.annotation:annotation:1.0.0' 223 | } 224 | } 225 | // Run this once to be able to run the application with BUCK 226 | // puts all compile dependencies into folder libs for BUCK to use 227 | task copyDownloadableDepsToLibs(type: Copy) { 228 | from configurations.compile 229 | into 'libs' 230 | } 231 | 232 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 233 | -------------------------------------------------------------------------------- /template/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /template/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/debug.keystore -------------------------------------------------------------------------------- /template/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 | -------------------------------------------------------------------------------- /template/android/app/src/androidTest/java/com/helloworld/DetoxTest.java: -------------------------------------------------------------------------------- 1 | package com.helloworld; 2 | 3 | import com.wix.detox.Detox; 4 | 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import androidx.test.ext.junit.runners.AndroidJUnit4; 10 | import androidx.test.filters.LargeTest; 11 | import androidx.test.rule.ActivityTestRule; 12 | 13 | @RunWith(AndroidJUnit4.class) 14 | @LargeTest 15 | public class DetoxTest { 16 | 17 | @Rule 18 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false); 19 | 20 | @Test 21 | public void runDetoxTests() { 22 | Detox.runTests(mActivityRule); 23 | } 24 | } -------------------------------------------------------------------------------- /template/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.helloworld; 8 | import android.content.Context; 9 | import com.facebook.flipper.android.AndroidFlipperClient; 10 | import com.facebook.flipper.android.utils.FlipperUtils; 11 | import com.facebook.flipper.core.FlipperClient; 12 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 13 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 14 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 15 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 16 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 17 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 18 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 19 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceManager; 22 | import com.facebook.react.bridge.ReactContext; 23 | import com.facebook.react.modules.network.NetworkingModule; 24 | import okhttp3.OkHttpClient; 25 | public class ReactNativeFlipper { 26 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 27 | if (FlipperUtils.shouldEnableFlipper(context)) { 28 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 29 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 30 | client.addPlugin(new ReactFlipperPlugin()); 31 | client.addPlugin(new DatabasesFlipperPlugin(context)); 32 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 33 | client.addPlugin(CrashReporterPlugin.getInstance()); 34 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 35 | NetworkingModule.setCustomClientBuilder( 36 | new NetworkingModule.CustomClientBuilder() { 37 | @Override 38 | public void apply(OkHttpClient.Builder builder) { 39 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 40 | } 41 | }); 42 | client.addPlugin(networkFlipperPlugin); 43 | client.start(); 44 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 45 | // Hence we run if after all native modules have been initialized 46 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 47 | if (reactContext == null) { 48 | reactInstanceManager.addReactInstanceEventListener( 49 | new ReactInstanceManager.ReactInstanceEventListener() { 50 | @Override 51 | public void onReactContextInitialized(ReactContext reactContext) { 52 | reactInstanceManager.removeReactInstanceEventListener(this); 53 | reactContext.runOnNativeModulesQueueThread( 54 | new Runnable() { 55 | @Override 56 | public void run() { 57 | client.addPlugin(new FrescoFlipperPlugin()); 58 | } 59 | }); 60 | } 61 | }); 62 | } else { 63 | client.addPlugin(new FrescoFlipperPlugin()); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /template/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /template/android/app/src/main/java/com/helloworld/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.helloworld; 2 | import android.os.Bundle; 3 | import com.facebook.react.ReactActivity; 4 | import com.zoontek.rnbootsplash.RNBootSplash; 5 | 6 | public class MainActivity extends ReactActivity { 7 | 8 | /** 9 | * Returns the name of the main component registered from JavaScript. This is used to schedule 10 | * rendering of the component. 11 | */ 12 | @Override 13 | protected String getMainComponentName() { 14 | return "HelloWorld"; 15 | } 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | RNBootSplash.init(R.drawable.bootsplash, MainActivity.this); // <- display the generated bootsplash.xml drawable 21 | // over our MainActivity 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /template/android/app/src/main/java/com/helloworld/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.helloworld; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = 17 | new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | @SuppressWarnings("UnnecessaryLocalVariable") 26 | List packages = new PackageList(this).getPackages(); 27 | // Packages that cannot be autolinked yet can be added manually here, for example: 28 | // packages.add(new MyReactNativePackage()); 29 | return packages; 30 | } 31 | 32 | @Override 33 | protected String getJSMainModuleName() { 34 | return "index"; 35 | } 36 | }; 37 | 38 | @Override 39 | public ReactNativeHost getReactNativeHost() { 40 | return mReactNativeHost; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | SoLoader.init(this, /* native exopackage */ false); 47 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 48 | } 49 | 50 | /** 51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 53 | * 54 | * @param context 55 | * @param reactInstanceManager 56 | */ 57 | private static void initializeFlipper( 58 | Context context, ReactInstanceManager reactInstanceManager) { 59 | if (BuildConfig.DEBUG) { 60 | try { 61 | /* 62 | We use reflection here to pick up the class that initializes Flipper, 63 | since Flipper library is not available in release mode 64 | */ 65 | Class aClass = Class.forName("com.helloworld.ReactNativeFlipper"); 66 | aClass 67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 68 | .invoke(null, context, reactInstanceManager); 69 | } catch (ClassNotFoundException e) { 70 | e.printStackTrace(); 71 | } catch (NoSuchMethodException e) { 72 | e.printStackTrace(); 73 | } catch (IllegalAccessException e) { 74 | e.printStackTrace(); 75 | } catch (InvocationTargetException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/drawable/bootsplash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /template/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Hello App Display Name 3 | 4 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /template/android/app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10.0.2.2 5 | localhost 6 | 7 | -------------------------------------------------------------------------------- /template/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "29.0.2" 6 | minSdkVersion = 18 7 | compileSdkVersion = 29 8 | targetSdkVersion = 29 9 | ext.kotlinVersion = '1.3.10' 10 | ext.detoxKotlinVersion = '1.3.0' // Detox' default is 1.2.0 11 | ext.detoxKotlinStdlib = 'kotlin-stdlib-jdk7' // Detox' default is kotlin-stdlib-jdk8 12 | } 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | dependencies { 18 | classpath("com.android.tools.build:gradle:3.6.2") 19 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 20 | 21 | 22 | // NOTE: Do not place your application dependencies here; they belong 23 | // in the individual module build.gradle files 24 | } 25 | } 26 | 27 | allprojects { 28 | task downloadDependencies() { 29 | description 'Download all dependencies to the Gradle cache' 30 | doLast { 31 | configurations.findAll().each { config -> 32 | if (config.name.contains("minReactNative") && config.canBeResolved) { 33 | print config.name 34 | print '\n' 35 | config.files 36 | } 37 | } 38 | } 39 | } 40 | repositories { 41 | mavenLocal() 42 | maven { 43 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 44 | url("$rootDir/../node_modules/react-native/android") 45 | } 46 | maven { 47 | // Android JSC is installed from npm 48 | url("$rootDir/../node_modules/jsc-android/dist") 49 | } 50 | maven { 51 | // All of Detox' artifacts are provided via the npm module 52 | url "$rootDir/../node_modules/detox/Detox-android" 53 | } 54 | google() 55 | jcenter() 56 | maven { url 'https://www.jitpack.io' } 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /template/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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.75.1 29 | -------------------------------------------------------------------------------- /template/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /template/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /template/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /template/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /template/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'HelloWorld' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /template/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HelloWorld", 3 | "displayName": "HelloWorld" 4 | } 5 | -------------------------------------------------------------------------------- /template/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ['module:metro-react-native-babel-preset'], 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /template/docs/circle-ci.md: -------------------------------------------------------------------------------- 1 | # CircleCI 2 | 3 | These instructions assume you have followed the installation instructions our [`hygen-templates-echobind` repository](https://github.com/echobind/hygen-echobind-templates). 4 | 5 | ## Setup CircleCI to build 6 | 7 | After generating a new project, add a GitHub remote and push up the changes. Login to CircleCI and head to the settings for your organization. 8 | 9 | 1. Ensure you've added a `MacOS` Plan. This is required to build iOS projects. 10 | 11 | ![Add MacOS plan](https://monosnap.com/image/BALZPhSmjwHMsmpa26CVS9DP1dFGbj.png) 12 | 13 | 2. Enable "untrusted or 3rd party orbs" under the organizations security settings. This step is required to use the provided CircleCI Orb configuration for react-native. 14 | Learn more about CircleCI Orbs [here](https://circleci.com/docs/2.0/using-orbs/). The source for the react-native orb is [here](https://github.com/echobind/circleci-react-native-orb). 15 | 16 | ![Orb Security Settings](https://monosnap.com/image/LSrtBdwDFJRh5HLaHbroKJx6cgqagC.png) 17 | 18 | 3. Tell Circle CI to build this project (must be logged in with an account that has owner permissions on GitHub). 19 | 20 | ![Add Project Image](https://monosnap.com/image/JWQQ5tlsOEBrKjpFnYDRdQOx9VCiVb.png) 21 | 22 | 4. Thats it! Your project should be building. Here's what the workflow looks like: 23 | 24 | ![Circle Workflow](https://monosnap.com/image/eT1Akkua4ZjsA72Ng4imma2qyFovLx.png) 25 | 26 | Once node tests (via jest) complete, iOS and Android builds run in parallel. See `.circleci/config.yml` for workflow details, including the Fastlane lanes that are run on each branch by default. 27 | -------------------------------------------------------------------------------- /template/docs/hygen-templates.md: -------------------------------------------------------------------------------- 1 | # Hygen Templates 2 | 3 | Templates can be found in the `_templates` directory at the root of the project. They are customizable generators that are meant to evolve alongside your code. 4 | 5 | Out of the box, we've wired up: 6 | 7 | - A component generator (`yarn g:component Button`). This will: 8 | - Prompt you if you want a functional or stateful component 9 | - add a Storybook story 10 | - A screen generator (`yarn g:screen LoginScreen`). This will: 11 | - Create a screen file that uses a general Screen wrapper component. 12 | - A util generator (`yarn g:util happy). This will: 13 | - Create a simple util function with a corresponding jest test. This will fail by default to encourage you to write them! 14 | - An E2E generator (`yarn g:e2e "My cool e2e test"`). This will: 15 | - Create a detox test in the `e2e` directory. 16 | 17 | We maintain additional templates related to CircleCi and Fastlane in the [`hygen-echobind-templates`](https://github.com/echobind/hygen-echobind-templates). You'll find instructions in that repository on how to use them to generate configs for your project. 18 | -------------------------------------------------------------------------------- /template/docs/navigation.md: -------------------------------------------------------------------------------- 1 | # Navigation 2 | 3 | This project uses react-navigation for navigating in the app. Out of the box, navigation consists of a few main concepts. 4 | 5 | ![Navigator Structure](https://monosnap.com/image/fCFp1XBi98Zy7HR9ZVJcPa1KEozeQI.png) 6 | 7 | ## Root Nav 8 | 9 | This navigator is rendered at the root of the app. It is a [SwitchNavigator](https://reactnavigation.org/docs/en/switch-navigator.html) and has 1 main responsibility: to take a `currentUser` object and render either an [Main Nav](#app-nav) or a [Guest Nav](#guest-nav) [StackNavigator](https://reactnavigation.org/docs/en/stack-navigator.html). 10 | 11 | ## Guest Nav 12 | 13 | This nav is a [StackNavigator](https://reactnavigation.org/docs/en/stack-navigator.html) that renders when a user is logged out of your app. Guest Nav screens typically consist of: 14 | 15 | - Onboarding 16 | - Registration 17 | - Login 18 | - Forgot Password 19 | 20 | ## App Nav 21 | 22 | This nav is a [StackNavigator](https://reactnavigation.org/docs/en/stack-navigator.html) that contains only the [Main Nav](#main-nav) by default. If you have any full screen modals that should render above the main nav UI, you should put them here. 23 | 24 | ## Main Nav 25 | 26 | Main Nav is meant to be the main interface of the app. By default it renders a [BottomTabNavigator](https://reactnavigation.org/docs/en/bottom-tab-navigator.html). 27 | 28 | ## Onboarding Nav (optional) 29 | 30 | This nav is a [StackNavigator](https://reactnavigation.org/docs/en/stack-navigator.html) that is meant to handle onboarding. We keep it as a separate stack from the [Guest Nav](#guest-nav). If your app doesn't need onboarding, feel free to delete this nav. 31 | -------------------------------------------------------------------------------- /template/docs/splashscreens.md: -------------------------------------------------------------------------------- 1 | # Splash Screens 2 | 3 | We've setup [react-native-splash-screen](https://github.com/crazycodeboy/react-native-splash-screen) for you! To customize it, follow the steps below. 4 | 5 | ## iOS 6 | 7 | 1. Create a 240px x 240px image @ 1x, 2x, and 3x sizes. 8 | 2. Open the project in Xcode. 9 | 3. Navigate to the `SplashScreen` image asset, and replace the items with your own: 10 | 11 | ![Changing Splash Image](https://monosnap.com/image/3yXqqL7NpQuyHvavHcwlJMGwShnPhA.png) 12 | 13 | 4. Update the background color or centering of the image by opening `LaunchScreen.xib` and adjusting the necessary properties: 14 | 15 | ![Updating Background](https://monosnap.com/image/PmScO75OOi1UaJgilexVL5TMYBRq3o.png) 16 | 17 | ![Updating Image](https://monosnap.com/image/a2YSVnuwvfRDlnS4CuB34kOhXGioIr.png) 18 | 19 | ## Android 20 | 21 | 1. Copy your 1x, 2x and 3x image assets into the proper mipmap folders (ldpi, xhdpi, and xxhdpi respectively) 22 | 23 | ![Adding images to Android folders](https://monosnap.com/image/AfviJGhxGZlw6xermUurFQVSUJ8pC5.png) 24 | 25 | 2. Update the color by changing the `launch_background` color in `android/app/src/main/res/values/colors.xml`. 26 | -------------------------------------------------------------------------------- /template/e2e/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "testEnvironment": "node", 3 | "reporters": ["detox/runners/jest/streamlineReporter"], 4 | "verbose": true, 5 | "setupFilesAfterEnv": ["./init.js"] 6 | } -------------------------------------------------------------------------------- /template/e2e/init.js: -------------------------------------------------------------------------------- 1 | /*global jasmine */ 2 | /*eslint no-undef: "error"*/ 3 | import detox, { device } from 'detox'; 4 | import adapter from 'detox/runners/jest/adapter'; 5 | import specReporter from 'detox/runners/jest/specReporter'; 6 | import config from '../.detoxrc.json'; // .detox; 7 | 8 | // Set the default timeout 9 | 10 | jest.setTimeout(120000); 11 | jasmine.getEnv().addReporter(adapter); 12 | 13 | // This takes care of generating status logs on a per-spec basis. By default, jest only reports at file-level. 14 | // This is strictly optional. 15 | jasmine.getEnv().addReporter(specReporter); 16 | 17 | beforeAll(async () => { 18 | await detox.init(config.detox, { launchApp: false }); 19 | await device.launchApp({ 20 | /** this is where you can set what permissions might be needed */ 21 | // permissions: { notifications: 'YES', camera: 'YES' }, 22 | newInstance: true, 23 | }); 24 | }); 25 | 26 | beforeEach(async () => { 27 | await adapter.beforeEach(); 28 | }); 29 | 30 | afterAll(async () => { 31 | await adapter.afterAll(); 32 | await detox.cleanup(); 33 | }); 34 | -------------------------------------------------------------------------------- /template/e2e/introScreen.spec.js: -------------------------------------------------------------------------------- 1 | describe('MyApp', () => { 2 | beforeEach(() => { 3 | device.reloadReactNative(); 4 | }); 5 | 6 | it('should have intro screen', () => { 7 | expect(element(by.id('introScreenText'))).toBeVisible(); 8 | expect(element(by.id('introScreenText'))).toHaveText('Welcome to the intro Screen!'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /template/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | fastlane_version '2.105.2' 2 | 3 | # before_all do 4 | # ensure_git_branch 5 | # ensure_git_status_clean 6 | # git_pull 7 | # end 8 | 9 | platform :ios do 10 | # iOS Lanes 11 | desc 'Fetch certificates and provisioning profiles' 12 | lane :certificates do 13 | match(app_identifier: 'com.HelloWorld.mobile', type: 'development', readonly: true) 14 | end 15 | 16 | desc 'generate iOS appiconset from master image' 17 | lane :icon do 18 | appicon( 19 | appicon_devices: [:iphone, :ios_marketing], 20 | appicon_path: "ios/HelloWorld/Images.xcassets" 21 | ) 22 | end 23 | end 24 | 25 | platform :android do 26 | desc 'generate Android launch icon from master image' 27 | lane :icon do 28 | android_appicon( 29 | appicon_image_file: 'fastlane/metadata/app_icon_android.png', 30 | appicon_icon_types: [:launcher], 31 | appicon_path: 'android/app/src/main/res/mipmap' 32 | ) 33 | 34 | android_appicon( 35 | appicon_image_file: 'fastlane/metadata/app_icon_android.png', 36 | appicon_icon_types: [:notification], 37 | appicon_path: 'android/app/src/main/res/mipmap', 38 | appicon_filename: 'ic_notification' 39 | ) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /template/fastlane/Pluginfile: -------------------------------------------------------------------------------- 1 | # Autogenerated by fastlane 2 | # 3 | # Ensure this file is checked in to source control! 4 | 5 | gem 'fastlane-plugin-appicon' 6 | -------------------------------------------------------------------------------- /template/fastlane/README.md: -------------------------------------------------------------------------------- 1 | # fastlane documentation 2 | 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | 13 | ``` 14 | [sudo] gem install fastlane -NV 15 | ``` 16 | 17 | or alternatively using `brew cask install fastlane` 18 | 19 | # Available Actions 20 | 21 | ## iOS 22 | 23 | ### ios certificates 24 | 25 | ``` 26 | fastlane ios certificates 27 | ``` 28 | 29 | Fetch certificates and provisioning profiles 30 | 31 | ### ios icon 32 | 33 | ``` 34 | fastlane ios icon 35 | ``` 36 | 37 | generate iOS appiconset from master image 38 | 39 | --- 40 | 41 | ## Android 42 | 43 | ### android icon 44 | 45 | ``` 46 | fastlane android icon 47 | ``` 48 | 49 | generate Android launch icon from master image 50 | 51 | --- 52 | 53 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 54 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 55 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 56 | -------------------------------------------------------------------------------- /template/fastlane/metadata/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/fastlane/metadata/app_icon.png -------------------------------------------------------------------------------- /template/fastlane/metadata/app_icon_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/fastlane/metadata/app_icon_android.png -------------------------------------------------------------------------------- /template/husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'pre-commit': 'lint-staged', 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /template/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | 3 | // Recommended in react-navigation v5 installation 4 | // https://reactnavigation.org/docs/getting-started/ 5 | import 'react-native-gesture-handler'; 6 | 7 | import App from './src/App'; 8 | import { name as appName } from './app.json'; 9 | 10 | AppRegistry.registerComponent(appName, () => App); 11 | -------------------------------------------------------------------------------- /template/ios/Dummy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dummy.swift 3 | // HelloWorld 4 | // 5 | // Created by Ryan Atkinson on 6/3/20. 6 | // 7 | 8 | import Foundation 9 | -------------------------------------------------------------------------------- /template/ios/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # gem "rails" 8 | gem "cocoapods", "1.8.4" -------------------------------------------------------------------------------- /template/ios/HelloWorld-Bridging-Header.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/ios/HelloWorld-Bridging-Header.h -------------------------------------------------------------------------------- /template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | #import "RNBootSplash.h" 7 | 8 | #ifdef FB_SONARKIT_ENABLED 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | static void InitializeFlipper(UIApplication *application) { 17 | FlipperClient *client = [FlipperClient sharedClient]; 18 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 19 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 20 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 21 | [client addPlugin:[FlipperKitReactPlugin new]]; 22 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 23 | [client start]; 24 | } 25 | #endif 26 | 27 | @implementation AppDelegate 28 | 29 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 30 | { 31 | #ifdef FB_SONARKIT_ENABLED 32 | InitializeFlipper(application); 33 | #endif 34 | 35 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 36 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 37 | moduleName:@"HelloWorld" 38 | initialProperties:nil]; 39 | 40 | if (@available(iOS 13.0, *)) { 41 | rootView.backgroundColor = [UIColor systemBackgroundColor]; 42 | } else { 43 | rootView.backgroundColor = [UIColor whiteColor]; 44 | } 45 | 46 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 47 | UIViewController *rootViewController = [UIViewController new]; 48 | rootViewController.view = rootView; 49 | [RNBootSplash initWithStoryboard:@"LaunchScreen" rootView:rootView]; 50 | self.window.rootViewController = rootViewController; 51 | [self.window makeKeyAndVisible]; 52 | return YES; 53 | } 54 | 55 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 56 | { 57 | #if DEBUG 58 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 59 | #else 60 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 61 | #endif 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/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 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /template/ios/HelloWorld/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 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 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | UIAppFonts 57 | 58 | FontAwesome.ttf 59 | MaterialIcons.ttf 60 | SimpleLineIcons.ttf 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /template/ios/HelloWorld/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /template/ios/HelloWorldTests/HelloWorldTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface HelloWorldTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation HelloWorldTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /template/ios/HelloWorldTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 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 | -------------------------------------------------------------------------------- /template/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '10.0' 5 | 6 | target 'HelloWorld' do 7 | config = use_native_modules! 8 | 9 | use_react_native!(:path => config["reactNativePath"]) 10 | 11 | target 'HelloWorldTests' do 12 | inherit! :complete 13 | # Pods for testing 14 | end 15 | 16 | # Enables Flipper. 17 | # 18 | # Note that if you have use_frameworks! enabled, Flipper will not work and 19 | # you should disable these next few lines. 20 | use_flipper!({ 'Flipper' => '0.75.1' }) 21 | post_install do |installer| 22 | flipper_post_install(installer) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /template/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "version": "0.0.1", 4 | "description": "a React Native app bootstrapped with the Echobind template", 5 | "private": true, 6 | "scripts": { 7 | "start": "react-native start --reset-cache", 8 | "test": "jest", 9 | "test:ci": "jest", 10 | "test:watch": "jest --changedSince=master --watch", 11 | "lint": "eslint . --ext .ts,.tsx", 12 | "g:component": "hygen component new --name", 13 | "g:screen": "hygen screen new --name", 14 | "g:util": "hygen util new --name", 15 | "g:e2e": "hygen e2e new --name", 16 | "ios": "react-native run-ios --simulator='iPhone 11'", 17 | "bundle:ios": "react-native bundle --entry-file='index.js' --bundle-output='./ios/main.jsbundle' --dev=false --platform='ios' --assets-dest='./ios'", 18 | "preandroid": "adb reverse tcp:3030 tcp:3030 && adb reverse tcp:9090 tcp:9090", 19 | "android": "react-native run-android", 20 | "android:clean": "cd android && ./gradlew clean && cd ..", 21 | "simulators": "xcrun simctl list", 22 | "emulators": "emulator -list-avds", 23 | "emulator:start": "emulator -avd", 24 | "e2e:ios-debug": "detox build -c ios.sim.debug && detox test -c ios.sim.debug --cleanup", 25 | "e2e:ios": "detox build -c ios.sim.release && detox test -c ios.sim.release --cleanup", 26 | "e2e:android-debug": "detox build -c android.emu.debug && detox test -c android.emu.debug -l trace --cleanup", 27 | "e2e:android": "detox build -c android.emu.release && detox test -c android.emu.release -l trace --cleanup" 28 | }, 29 | "keywords": [], 30 | "author": "", 31 | "license": "ISC", 32 | "dependencies": { 33 | "@emotion/core": "^10.0.6", 34 | "@emotion/native": "^10.0.6", 35 | "@react-native-community/masked-view": "^0.1.10", 36 | "@react-navigation/bottom-tabs": "^5.6.1", 37 | "@react-navigation/native": "^5.6.1", 38 | "@react-navigation/stack": "^5.6.2", 39 | "emotion-theming": "^10.0.19", 40 | "react": "16.13.1", 41 | "react-native": "0.63.2", 42 | "react-native-bootsplash": "^3.1.2", 43 | "react-native-elements": "^1.2.7", 44 | "react-native-gesture-handler": "^1.6.1", 45 | "react-native-reanimated": "^1.9.0", 46 | "react-native-safe-area-context": "^3.0.7", 47 | "react-native-safe-area-view": "^1.0.0", 48 | "react-native-screens": "^2.9.0", 49 | "react-native-vector-icons": "6.6.0", 50 | "styled-system": "^5.1.2" 51 | }, 52 | "devDependencies": { 53 | "@babel/core": "^7.8.4", 54 | "@babel/runtime": "^7.8.4", 55 | "@react-native-community/eslint-config": "^1.1.0", 56 | "metro-react-native-babel-preset": "^0.59.0", 57 | "react-test-renderer": "16.13.1", 58 | "@storybook/addon-ondevice-backgrounds": "^5.2.5", 59 | "@storybook/addons": "^5.2.5", 60 | "@storybook/react-native": "^5.3.0-rc.1", 61 | "@types/jest": "^24.0.18", 62 | "@types/node": "^12.7.7", 63 | "@types/react": "^16.9.0", 64 | "@types/react-native": "^0.60.15", 65 | "babel-jest": "^25.1.0", 66 | "detox": "^17.14.1", 67 | "enquirer": "^2.3.0", 68 | "eslint": "^6.6.0", 69 | "eslint-config-prettier": "^6.5.0", 70 | "eslint-plugin-echobind": "^0.2.0", 71 | "eslint-plugin-prettier": "^3.1.1", 72 | "husky": "^1.2.1", 73 | "hygen": "^2.0.4", 74 | "jest": "^25.1.0", 75 | "lint-staged": "^10.0.0-beta.3", 76 | "prettier": "^1.19.1", 77 | "react-native-flipper": "^0.73.0", 78 | "solidarity": "^2.3.1", 79 | "ts-jest": "^23.10.5", 80 | "typescript": "^3.2.2", 81 | "typescript-styled-plugin": "^0.13.0" 82 | }, 83 | "jest": { 84 | "preset": "react-native", 85 | "moduleFileExtensions": [ 86 | "ts", 87 | "tsx", 88 | "js" 89 | ], 90 | "globals": { 91 | "ts-jest": { 92 | "tsConfig": { 93 | "isolatedModules": false 94 | } 95 | } 96 | }, 97 | "transform": { 98 | "^.+\\.(js)$": "/node_modules/react-native/jest/preprocessor.js", 99 | "\\.(ts|tsx)$": "ts-jest" 100 | }, 101 | "testRegex": "(/__tests__/.*|(test|spec))\\.(ts|tsx|js)$", 102 | "testPathIgnorePatterns": [ 103 | "\\.snap$", 104 | "e2e", 105 | "/node_modules/" 106 | ], 107 | "cacheDirectory": ".jest/cache" 108 | }, 109 | "lint-staged": { 110 | "**/*.{ts,tsx}": [ 111 | "yarn lint --fix", 112 | "git add" 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /template/react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assets: ['./src/assets/fonts/'], 3 | }; 4 | -------------------------------------------------------------------------------- /template/rn-cli.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // should only be required for < 0.57 3 | // getTransformModulePath() { 4 | // return require.resolve('react-native-typescript-transformer'); 5 | // }, 6 | getSourceExts() { 7 | // allow overrides via ENV vars (ex: component.e2e.js) 8 | return process.env.RN_SRC_EXT 9 | ? process.env.RN_SRC_EXT.split(',').concat(['ts', 'tsx']) 10 | : ['ts', 'tsx']; 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /template/setup/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { execSync } = require('child_process'); 4 | const { prompt } = require('enquirer'); 5 | 6 | async function setup() { 7 | const deleteFile = fileName => fs.unlinkSync(path.join(__dirname, fileName)); 8 | const deleteDirectory = dirName => fs.rmdirSync(path.join(__dirname, dirName)); 9 | const writeFile = (fileName, data) => fs.writeFileSync(path.join(__dirname, fileName), data); 10 | 11 | console.log('\n🤔 Checking system setup and prerequisites...'); 12 | try { 13 | execSync('yarn solidarity --verbose', { stdio: 'inherit' }); 14 | } catch { 15 | // Bail if solidarity checks fail 16 | return; 17 | } 18 | 19 | console.log('\n📝 Configuring project display name and bundle identifier...'); 20 | const { displayName } = await prompt({ 21 | type: 'input', 22 | name: 'displayName', 23 | message: 'App Display Name (ProjectName):', 24 | initial: 'HelloWorld', 25 | }); 26 | 27 | const { bundleIdentifer } = await prompt({ 28 | type: 'input', 29 | name: 'bundleIdentifer', 30 | message: 'App Bundle Identifier', 31 | initial: displayName.toLowerCase() || 'helloworld', 32 | }); 33 | 34 | const { confirmed } = await prompt({ 35 | type: 'confirm', 36 | name: 'confirmed', 37 | message: `Continue with => App Display Name: ${displayName} | App Bundle Identifer: ${bundleIdentifer}`, 38 | }); 39 | 40 | if (!confirmed) { 41 | console.log('\n Cannot continue without choosing a display name and app bundle identifier...'); 42 | console.log('\n Exiting setup...'); 43 | return; 44 | } 45 | 46 | const { shouldInitializeGitRepository } = await prompt({ 47 | type: 'confirm', 48 | name: 'shouldInitializeGitRepository', 49 | message: 'Would you like to initialize this project as a git repository?', 50 | }); 51 | 52 | console.log('🔄 Setting up...'); 53 | console.log('\n🛠 Setting up fastlane and installing app icons...'); 54 | const rootDirectory = path.join(__dirname, '../'); 55 | execSync('bundle install', { cwd: rootDirectory }); 56 | execSync('bundle exec fastlane ios icon', { cwd: rootDirectory }); 57 | execSync('bundle exec fastlane android icon', { cwd: rootDirectory }); 58 | 59 | console.log('\n Updating project display name and bundle identifier...'); 60 | execSync(`npx react-native-rename ${displayName} -b ${bundleIdentifer}`, { 61 | cwd: rootDirectory, 62 | }); 63 | 64 | execSync( 65 | `bundle exec fastlane run update_app_identifier app_identifier:"${bundleIdentifer}" plist_path:"${displayName}/Info.plist" xcodeproj:"ios/${displayName}.xcodeproj"`, 66 | { cwd: rootDirectory }, 67 | ); 68 | 69 | console.log('\n☕ Installing Cocoapods...'); 70 | execSync('bundle install', { cwd: 'ios' }); 71 | execSync('bundle exec pod install', { cwd: 'ios' }); 72 | 73 | execSync( 74 | `HYGEN_OVERWRITE=1 yarn hygen setup splashscreen ios --displayName ${displayName} --bundleIdentifer ${bundleIdentifer}`, 75 | ); 76 | 77 | console.log('\n🤖🌊 Setting up android splash screens...'); 78 | execSync( 79 | `HYGEN_OVERWRITE=1 yarn hygen setup splashscreen android --displayName ${displayName} --bundleIdentifer ${bundleIdentifer}`, 80 | ); 81 | 82 | console.log('\n🗑 Removing cruft...'); 83 | execSync('rm -rf setup', { cwd: rootDirectory }); 84 | execSync('rm -rf .git', { cwd: rootDirectory }); // blow away old repo if there 85 | 86 | if (shouldInitializeGitRepository) { 87 | console.log('\n📝 Committing project...'); 88 | execSync( 89 | 'rm -rf .git && git init && git add . && git commit -m "Initialize new React Native project."', 90 | { 91 | cwd: rootDirectory, 92 | }, 93 | ); 94 | 95 | console.log('\n📱 Setting initial version @0.0.1 ...'); 96 | execSync('npx react-native-version --never-increment-build', { 97 | cwd: rootDirectory, 98 | }); 99 | 100 | console.log('\n📝 Committing changes...'); 101 | execSync('git add . && git commit -m "Set proper initial symver version"', { 102 | cwd: rootDirectory, 103 | }); 104 | } 105 | 106 | console.log(`\n✅ Setup completed!`); 107 | console.log('\n\n------------------------'); 108 | console.log('** PostInstall Notes: **'); 109 | console.log('------------------------\n\n'); 110 | console.log('\n* Check out the docs folder to customize and finalize your app!'); 111 | console.log('\n'); 112 | } 113 | 114 | setup(); 115 | -------------------------------------------------------------------------------- /template/splashscreenPreview/SplashScreens-iPhone12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/splashscreenPreview/SplashScreens-iPhone12.gif -------------------------------------------------------------------------------- /template/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement, useEffect } from 'react'; 2 | import RNBootSplash from 'react-native-bootsplash'; 3 | import { SafeAreaProvider } from 'react-native-safe-area-context'; 4 | import { NavigationContainer } from '@react-navigation/native'; 5 | import { ThemeProvider } from 'emotion-theming'; 6 | 7 | import Storybook from '../storybook'; 8 | import { AppNav } from './navigation/AppNav'; 9 | import { GuestNav } from './navigation/GuestNav'; 10 | 11 | import { theme } from './styles'; 12 | 13 | // NOTE: Change this boolean to true to render the Storybook view for development! 14 | const RENDER_STORYBOOK = false; 15 | 16 | const App = (): ReactElement | null => { 17 | // hide the splashscreen on mount 18 | useEffect(() => { 19 | RNBootSplash.hide({ fade: true }); 20 | }, []); 21 | 22 | const renderNavigation = (): ReactElement => { 23 | // replace with actual user profile data once loaded, or fallback to guest nav 24 | const currentUser = false; 25 | 26 | return currentUser ? : ; 27 | }; 28 | 29 | return ( 30 | 31 | 32 | 33 | {RENDER_STORYBOOK ? : renderNavigation()} 34 | 35 | 36 | 37 | ); 38 | }; 39 | 40 | export default App; 41 | -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-Bold.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-BoldItalic.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-Italic.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-Medium.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-MediumItalic.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-Regular.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-SemiBold.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Archivo-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Archivo-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /template/src/assets/fonts/Blockletter.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/fonts/Blockletter.otf -------------------------------------------------------------------------------- /template/src/assets/fonts/README.md: -------------------------------------------------------------------------------- 1 | Add fonts here and run `react-native link` 2 | -------------------------------------------------------------------------------- /template/src/assets/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/images/background.png -------------------------------------------------------------------------------- /template/src/assets/images/background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/images/background@2x.png -------------------------------------------------------------------------------- /template/src/assets/images/background@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/echobind/react-native-template/d4dc46369d6162f48264266fe4b953f7deff8c72/template/src/assets/images/background@3x.png -------------------------------------------------------------------------------- /template/src/components/Button/Button.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react-native'; 2 | import React from 'react'; 3 | 4 | import { Button } from './Button'; 5 | 6 | storiesOf('components/Button', module).add('Default', () => ( 7 |