mkraenz / you-are-awesome-app

Community-driven motivational quotes. Every day you receive an awesome message from a grateful person around the globe. Share your own gratitude by contributing awesome quotes yourself.
https://play.google.com/store/apps/details?id=eu.kraenz.youareawesomeapp
1 stars 0 forks source link
android app expo react react-native

You are Awesome App! Daily Motivation Up

Community-driven motivational quotes.

Receive Motivation each day. Boost your Productivity. Share your gratitude to make this world even more awesome. Join our Awesome Community.

How it works: Each day you receive a motivational message written by a grateful person around the globe. That's it. No magic. Only gratefulness. Either via push notification or directly in the app.

Get it on Google Play Twitter URL

you are awesome app home screen

you are awesome app favorites screen

you are awesome app contribution screen

you are awesome app settings screen

you are awesome app favorites screen dark theme

Getting Started

Prerequisites

Please contact the repo owner for Windows support.

Installation

git clone https://github.com/proSingularity/you-are-awesome-app.git
# Make sure to use yarn instead of npm
yarn quick-setup
yarn dev
# a QR code will appear in the console

For a walkthrough with pictures, see Expo Docs Walkthrough.

More Advanced

Emulator vs Device

Alternative to Expo Go, you can run setup an Android Emulator (on any host operating system) or iOS Simulator (only on MacOS). See Expo's Guide to Android Studio Emulator.

Google and Firebase integration

.env, google-services.json, GoogleService-Info.plist are generated with fake data. This fake data suffices to run most of the app. Some features like Google Analytics for Firebase are not available though. The real data may only be shared internally. Talk to the repo owner.

Production

Production apps are apps on a User's smart phone installed from the Google Play Store.

Legals

Legal Attributions

Google Play and the Google Play logo are trademarks of Google LLC.

Releases

OTA Over-the-air updates

yarn deploy:ota:stage
# for production release
yarn deploy:ota:prod

When a User now starts her app (even if installed from the Google Play Store!), the app tries to download the newest JS files for the app and runs the newest version. It falls back to the cached (i.e. previous) version after 2 seconds.

Special case - changes to app.json or Expo SDK

Only in case of changes to app.json or the Expo SDK version, one needs to rebuild the app and republish to expo.

# manually update app.json's version, android.versionCode, and js version
# requires eas-cli installed
yarn eas build --platform android --profile production

To push the built apk to the Google Playstore, run

# ensure the following was run right before publishing to playstore
# yarn build-and-publish:expo:android:app-bundle:prod
# then download the .aab to your local machine
yarn eas submit --platform android --profile production
# select `Provide a path to a local app binary file`
# paste the path to your .aab file

## NOTE: the workflow should soon be optimized for use of EAS Build, which works well together with EAS Submit

google-services.json in EAS Build

yarn eas secret:create --scope=project --name=Y3A_GOOGLE_SERVICES --value="$(cat ./google-services.json | base64 --wrap 0)"

Testing Releases: app-bundle

When using build target app-bundle (.aap) instead of .apk you cannot immediately install them on a device. To test the app on emulator, you need to create an .apk as follows:

# unpacks the .aab to apk-archive (.apks, essentially .zip)
java -jar bundletool.jar build-apks --bundle=you-are-awesome-app-f91e1a4501e44622b4de84267a774a23-signed.aab --output=y3a.apks --mode=universal

# Option A: install app on a device (like adb install)
java -jar bundletool.jar install-apks --apks=y3a.apks

Alternative to Option A:

# Option B: extract the real app (.apk) living inside the .apks as universal.apk
unzip -p y3a.apks universal.apk > y3a.apk
adb install -r ./y3a.apk

Reference on StackOverflow

Development

Main reference

Debug native app on a phone or emulator

Requires

Pro tip: Use zsh (zshell) for autocompletion of paths, and even for adb.

# list connected devices
adb devices -l

# native logs
adb logcat
adb logcat | tee --append android-usb-debugging.log

# install apk
adb install /path/to/my/app
adb install ~/Downloads/you-are-awesome-app-8497638a825d4c70988a0c68eec2d09b-signed.apk
# if app already installed, then re-install
adb install -r ~/Downloads/you-are-awesome-app-8497638a825d4c70988a0c68eec2d09b-signed.apk

Debugging Jest tests

Further reading in related issue #16 .

Further Links

Frequent Development Questions and Mistakes

Clear expo cache

expo start --clear
yarn dev --clear

ReferenceError: Can't find variable: React

Having a react component import from react like this

import { FC } from "react";

will result in ReferenceError: Can't find variable: React.

Solution

import React, { FC } from "react";

During tests: Unable to find node on an unmounted component

Unable to find node on an unmounted component.

at node_modules/@testing-library/react-native/build/helpers/findByAPI.js:16:115
at Timeout.runExpectation [as _onTimeout] (node_modules/@testing-library/react-native/build/waitFor.js:48:24)

If this happens in places where the Portal component is used, first check that the state is mocked correctly (including for all rendered subcomponents).

Redux: I connected my component with the action creator but the reducer doesn't receive any actions

When your imported action creater and the Prop for the action creator are named identically, TypeScript doesn't care which one you use inside the component. So make sure you use the action creator from the Props. Only the action creator from the props is actually connected to the redux store.

import { actionCreator } from "./actionCreator";
interface Props {
  actionCreator: typeof actionCreator;
}
// make sure you use the action creator from the props.
// TS won't recognize if you don't destructure the props.
const MyComponent: FC<Props> = ({ actionCreator }) => {
  return <Button onPress={actionCreator}>Do something</Button>;
};

const mapStateToProps = (state: IState) => state;
const mapDispatchToProps: Props = {
  actionCreator,
};
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);