Tradle App
tim = Trust in Motion
Welcome to the main repo for the Tradle app! On mobile we use React Native (RN), and on web React Native Web (RNW). The web app currently lives on the web
branch.
Development
Prerequisites
- node 8.10
- npm 3.10 (if you have a newer one, downgrade it: npm install -g npm@3.10
- React Native Debugger
iOS
Install the latest Xcode command line tools:
xcode-select --install
Install
We recommend you have two separate development environments for mobile and web so you switch off quickly without going through a length npm install
in between.
Mobile
git clone https://github.com/tradle/tim tradle-app
cd tradle-app
npm install
# iOS
# install more dependencies via CocoaPods
cd iOS
pod install
bundle install # install fastlane and other gems
cd fastlane
fastlane install_plugins
cd ../../
# Android
cd android
bundle install
cd fastlane
fastlane install_plugins
cd ../
Web
git clone https://github.com/tradle/tim tradle-app-web
cd tradle-app
git checkout -b web origin/web
npm install
Run in Dev Mode
Mobile
- Start the RN packager
npm start
- Deploy the app to a simulator / device
react-native run-ios # to deploy to device, open Xcode, and Run with your device selected
react-native run-android
- Open the React Native Debugger if you want to debug JS
Web
- Start Webpack
npm start
- Open
http://localhost:3001
in the browser
Release
Prerequisites
- jq: a great command line JSON parser (On OS X, you can
brew install jq
) - AWS CLI
- ask someone at Tradle for access to release credentials
npm run loadsecrets
Mobile
There are several release lifecycles, broadly:
- publishing to the app store. This is required any time there's a change to any native component (Obj-C / Java).
- pushing a new JS bundle via React Native Code Push
The Apple App Store takes a while to approve releases, and even the Google Play Store can take an hour to publish your latest release. And after publishing, you still need to get your users to install the latest version.
Code Push to the rescue! Code Push allows to release new javascript bundles to already running apps so they can update themselves. Reminder: React Native apps consist of native code (Obj-C / Java) and a javascript bundle. Code Push can only push a new javascript bundle and assets such as images. If native code has changed, you MUST publish through the app store.
To build and publish releases for iOS and Android, we use fastlane.
To see what fastlane actions are available, cd
to the iOS/
or android/
dirs and run fastlane
Potential improvements:
Version and tag
Create a tagged commit for a given type of version release. Keep in mind that build numbers mean different things in iOS and Android.
- Android: build number inexorably increases. Maybe the build number ice caps are melting? Someone should check.
- iOS: build number currently resets to 0 after one of major/minor/patch is incremented. However, maybe we should change this to be more like Android.
# in iOS/ or android/
fastlane inc_build
fastlane inc_patch
fastlane inc_minor
fastlane inc_major
Code Push
# in iOS/ or android/
# dry run
fastlane codepush dry_run:true
# actually build and push
fastlane codepush
# promote from Staging to Release
fastlane codepush_promote_to_release
App Store
So you changed something on the native side? Or maybe you want to spare users the extra refresh? Let's do it.
Note: the approaches for iOS and Android a little different. It would be good to unify them
iOS
Start by pushing a build to TestFlight and Crashlytics:
fastlane beta
Then publish to the App Store
fastlane release
Android
Deploy a release to the Google Play Store internal track (private to Tradle devs and individually added users).
fastlane release_staging
Deploy a release to the Google Play Store closed alpha or open beta tracks:
fastlane release_alpha
fastlane release_beta
Deploy a production release:
fastlane release_prod
Troubleshooting
This is a complex app. Sometimes things go wrong. Have a good cry, then read on.
Many errors are documented widely in the various React Native communities. Some are specific to our setup.
Because this module relies on functionality that in Node.js is handled by core libraries, we rely on a number of shims to approach compatibility with Node.js. If you're used webpack/browserify to bundle a Node.js app, you might be familiar with this concept. To install these shims and monkeypatch substitution mappings (browser
and react-native
fields) through package.json
files in the dependency tree, we've developed rn-nodeify. Yes, the monkeypatching is unfortunate, but at the moment there doesn't seem to be a more stable solution to this problem. This is done in the postinstall
scripts.
With that in mind, whenever you do anything that changes the dependency tree (e.g. npm install
/ npm uninstall
) if you experience some problem with the packager, it is often a case of running npm run postinstall
, and then restarting the packager.
Memorize these commands, you'll need them:
watchman watch-del-all
npm start -- --reset-cache # start packager with clean cache
Pods
Make sure you have cocoapods
1.5.3 installed, for some reason 1.6.1 doesn't generate iOS/Pods/Headers/Public
To make sure:
sudo gem uninstall cocoapods
# choose to uninstall all versions
sudo gem install cocoapods -v 1.5.3
iOS builds
- if you're building Staging and see an error during archive that mentions Pods, try running:
./scripts/fix-staging.js
and then trying again
Android dev
Symptom: red screen of death: 'Unable to load script from assets main.jsbundle...' or 'Could not connect to development server'
Causes: your Android device is not connected, or can't reach your React Native packager's local http server
Fix: Check your device is connected: adb devices
. Once you see it there, run adb reverse tcp:8081 tcp:8081
and then refresh on your device
Symptom: red screen of death: Unexpected character '*'
Cause: iOS and Android (in dev mode) need different .babelrc settings
Fix: in .babelrc, the "development" block, find generators: false
, and set to true
. Then restart your packager with --reset-cache
. Please don't commit .babelrc with this change
Symptom: adb devices command returns empty list when the device is USB connected. Fix: Make sure your device is not connected as a media device. On your Android phone got Settings -> Developer options -> Networking -> Select USB Configuration
Localization
When a new message added in the app to utils/strings_en.js it needs to be translated to all the languages the app supports. These are the messages that are displayed as alerts, greeting/standard messages to the customer, or in progress popups.
All the translation files reside in S3.
That is why the translation script should be ran with AWS_PROFILE environment variable like this:
AWS_PROFILE=[profile] npm run translate:strings