Banana App is an open-source, not-for-profit project of The Be Good Foundation. We can reduce hunger by simplifying food donation. We make it easy for grocery stores and restaurants to donate good food that would otherwise be disposed of. Users will be able to find active donations, view the business's food rating, and claim a portion.
- BANANA APP
- The rest of The Banana App family:
- Contributing
- Dev Notes
- Deployment
NOTE: If you notice any outdated information or instructions in this README, please don't hesitate to open a PR and fix any discrepancies!
(NOTE: unclear if these still are accurate..)
Step 0 is to install the backend. Follow those instructions to make sure you have everything needed to install this repo (like the Xcode command line tools).
Step 1 is to navigate to your project's root folder in the terminal (e.g. cd ~/Projects/banana-rn)
First we install NVM and Node
npm i -g nvmORcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash
Install Xcode for the iOS simulator. This takes a while.
- Go to this website and follow the instructions for installing Node Version Manager for Windows NOTE: This is necessary as the Banana app uses an older version of Node. This is also very convenient as it will let you switch between previous (or current) versions of Node depending on which project you're working on.
-
To confirm installation on either mac or windows, open up your Command Prompt and run
nvm --versionand it should return the version of your NVM and a list of its usage. -
Once that's done, run
nvm use(Banana App's config are compatible with Node version <= 12.10.0) and if you dont have the necessary version follow the prompt to install it (e.g.nvm install 12.13.0). [NOTE: Runnvm listornvm lsto see all of your saved versions of Node. You can use the same commandnvm use [version]to switch]. -
Run
npm i -g expo-clito enable expo cli globally. -
Make sure you've traversed to your desired project directory and run
git clone https://github.com/FoodIsLifeBGP/banana-rn && cd banana-rn && npm i
-
Download the latest version of Android Studio here and complete the installation. No other configurations needed.
-
Once downloaded, open Android Studio and a little start up box should open. Go to the bottom right corner of that box and find "Configure" and select SDK manager.
-
Under
Appearance & Behavior > System Settings > Android SDK settingsand SDK Platforms tab. Make sure you have Android 10.0 (Q) and Android 9.0(Pie) checked (also feel free to check other Android versions, all up to your preference). -
Under the same settings / page, but on the SDK Tools Tab, Make sure you have Google Play and Android SDK Platform-Tools services checked and leave the rest untouched.
-
Click "Apply" and "OK" to exit out.
-
On the start up box, click on "Configure" one more time and select "AVD Manager". This AVD Manager shows you the list of Android emulators you have ready.
-
To create a new device, simply click on "Create Virtual Device" at the bottom left.
-
Select what kind of device you'd like to work with, but Pixel 2 does the job well and click "Next".
-
Select which system image you want on the device. Simply hit the "Download" button next to the name and wait for it. Once downloaded, select it and hit "Next".
-
Verify all the configurations (name, startup orientation, etc.) and click "Finish" when done.
-
The configuration box will close, and your new device should appear on your list of Virtual Devices. Select your choice, and click the green button under the "Actions" tab over on the right side of the window to launch the emulator.
As of mid July 2020, we have combined expo config across app.json and app.config.js so that we can publish our
progress to expo.io so that non-developers can view the current state of the app and also so that devs can change aspects
of their config (donor vs. client) or what backend server they're using without having to make a change to a file under
source control. However, this means that you'll need to be using a newer version of expo--3.20+. If you get an error:
TypeError: Cannot read property 'variant' of undefined chances are that your version of expo is not compatible with the
updated config. You can update your expo with npm install -g expo-cli and this may also require you to update your
node version--sorry!
Take note of app.config.js in the root. This is where we specify whether to compile the donor or client app.
You can most easily switch between donor and client by creating a .env file in the project root and adding an entry
for EXPO_APP_VARIANT e.g. EXPO_APP_VARIANT=client this way you can make this change locally without editing a file that's under
git control. Note that all variables in .env will need to be prefixed with EXPO_ since expo restricts things
that way.
export default ({ config }) => ({
...config,
extra: {
ipAddress: process.env.EXPO_IP_ADDRESS,
variant: process.env.EXPO_APP_VARIANT ? process.env.EXPO_APP_VARIANT : 'donor',
storybook: process.env.EXPO_STORYBOOK ? process.env.EXPO_STORYBOOK === 'true' : false,
},
});Now run:
expo start(orexpo r. Later, you may want to useexpo r -cto clear the cache.)
A tab in your web browser will open showing the Expo dashboard. To open the app in either iOS or Android Simulator, hit the link button marked open in iOS/Android Simulator, on the left-hand side of the dashboard. You can also follow the Expo docs to open the app on your phone, or the Android simulator.
When the app opens, you will see the login screen. Assuming you are still running the Rails server in the background, you can log in with the sample account for your variant:
- email:
donor@donor.com, password:donor@123 - email:
client@client.com, password:client@123
or create a new account.
environments.tscontrols what rails server the app will try to talk to.- The default is an AWS server running the latest banana rails from the
prealpha/mainbranch. - If you would like to talk to a different rails server (most likely your own in the event you have changes you want to test), create a file called
.envin your project root and addIP_ADDRESS=<your internal network ip>to the file (you can also change the variant to client in the.envfile)
- If you elect to use your web browser to test your changes, Firefox may just render a blank page. Switching to another browser should resolve the issue.
Back End - Ruby on Rails/Postgres Back End
Admin - React / Storybook
- Clone the repo,
- Checkout a new branch from your local copy of main
- Make your changes using the pattern:
feature/my-great-feature,fix/my-great-fix - Push your changes and create a pull request
- Tag a reviewer when your code is ready
- Once your review has been approved, make sure you squash and merge so as not to pollute the commit history with a bunch of extraneous commits
In order to merge your PR, the code will need to pass linting and typechecking. The style guide is extended from AirBnB's. To check your branch before making a pull request, run the following:
npm run lintnpm run lint:fix(changes/fixes are made if possible)npm run typechecking
Warnings should not prevent a merge.
Take in userIdentity from state (see State Management). This will always be either donor or client. (The app won't boot otherwise.)
This can be used to change strings - (${userIdentity === 'donor' ? 'Donations' | 'Claims'}) - or for bigger features (conditional/split components, backend routes, etc).
If using VS Code, we recommend the following extensions:
- ESLint
- TSLint
- GitLens
- Code Spell Checker
If you are ever having trouble running the app after pulling an update, try
npm run reset(deletes/node_modules&package-lock.json, runsnpm i, and deleteswatchmancache)- uninstall the Expo app from your device or sim
- run
expo start --clear(orexpo r -c)
Absolute imports are available for the following folders: assets, elements, screens, util, and state. Use the @ symbol to access them (i.e. import Component from '@screens/component).
- To add more, use examples from and update the relevant fields in:
.eslintrc.js,babel.config.js,tsconfig.json
TODO: make absolute imports work for the MenuDrawer. Any new elements should be configured so they can be imported as such:
import { NewElement, OldElement } from '@elements';
zustand is a small (~1kb) state management solution for React that is also simple and fast. It is built upon the concept of state atoms and allows us to use hooks as the primary means to subscribe to state changes.
The state management file is located in @state/index.ts. The initial state is defined in the initialState constant. The usage of zustand involves calling a hook that returns the store, which includes the state and all actions that can be called.
- Define
counter: 0in initialState. - All properties should be defined in the state file additionally actions should be defined an actions file in the @state/actions directory and then imported into the state file.
- Here's an example of an action, increase, that adds a certain amount to the counter value.
//@state/index.ts
const useGlobalStore = create<GlobalState>((set) => ({
...initialState,
increase: (amount) => set((state) => ({ counter: state.counter + amount })),
// other actions...
}));- Import & access the store in your component:
import useGlobalStore from '@state';
const ExampleComponent = () => {
const increase = useGlobalStore((state) => state.increase);
const count = useGlobalStore((state) => state.count);
return (
<Button
onPress={() => increase(1)}
/>
`Count: ${count}`
</Button>
);
}The variant field in app.json/expo/extra is used to set some psuedo-environment variables. These values are then immediately loaded into state, so they're only to be used before state is initialized. That is to say, hopefully you will never have to use them. But if you do, they live in /src/util/environment.ts. The API URL root also lives here.
import getEnv from '@util/environment';- in body:
const { NEW_VARIABLE } = getEnv();
The icon system enables dynamically colored icons for mobile, and statically rendered icons for browser. The Icon component ensures consistent usage of the each icon/icon pairs.
import { Icon } from '@/elements';
...
<Icon name="arrowDown" color="pink" size={24} />Any new SVG icons will have to follow some standards in order to work with the icon system.
- Convert all open paths with stroke to closed paths without stroke.
- Use a 'Stroke to Path' feature in a vector editing software.
- This ensures that the 'fill' attribute is the only variable to change in order to alter icon colors.
- Only one dynamic color per icon.
- If an icon has more than one color (e.g. NavBar icons with red notification dots), the non-color-dynamic SVG elements must have a fill attribute set to their static color.
- Any color-dynamic parts of the icon must not have a fill attribute. They will inherit the root element's fill color.
<path fill="red" ... />
- The root element,
<svg fill="#000000" ... >, must have a fill color.- In order for static rendering to work, a fill color must be provided to the SVG root element.
- This fill color is overwritten with JS.
- Be wary of declaring presentation attributes within a
styleattribute. These cannot be overwritten.
Some icons need to seamlessly replace each other in order to simulate animation.
Note: The term Base icon means the main part of the icon versions that don't change. Think the hamburger menu lines, not the red notification dot.
- Viewbox dimensions must envelope all SVG versions of the icon.
- Each icon version must share the same viewbox dimensions.
- The icon versions might need to be offset or given alternate dimensions.
- In order for asymetrical icon groups to be positioned properly (i.e. centered), offset distances and dimension scaling ratios should be provided within the Icon component in order for the 'base icon' to be present properly.
SVGs are imported differently depending on if the build is for mobile or browser.
In mobile device bundling, SVGs are imported as dynamic React Components.
import { SvgImage } from '@assets/image.svg';
...
<SvgImage ... />In browser webpacking, SVGs are imported as static URIs (e.g. server assets path, data blob URI, etc.).
import { SvgImage } from '@assets/image.svg';
...
<Image source={SvgImage} ... />import { SvgImage } from '@assets/image.svg';
import { Platform } from 'react-native';
...
if (Platform.os === 'web') {
<Image source={SvgImage} ... />
} else {
<SvgImage ... />
}- The following variables are set in 'app.client.json'
- “name": "The Banana App - Client"
- “version”: “this should be set dependent on the current version found on https://appstoreconnect.apple.com”
- "slug": "banana-app-client"
- "bundleIdentifier": "com.thebegoodproject.org.bananaapp-client"
- The following variables are set in 'app.donor.json'
- "name": "The Banana App - Donor"
- “version”: “this should be set dependent on the current version found on https://appstoreconnect.apple.com”
- "slug": "banana-app-donor",
- "bundleIdentifier": "com.thebegoodproject.org.bananaapp"
npm install- Increment the version according to version number in the appropriate file:
'app.client.json' || 'app.donor.json'
- Start the desired app to ensure there are no errors:
expo start --config app.client.json || expo start --config app.donor.json
- In your browser choose “Run on iOS simulator”
- Create your desired build of the app to upload:
expo build:ios --config app.client.json
OR
expo build:ios --config app.donor.json
- Choose “archive” when asked to “Choose the build type you would like”
- Follow prompts
- The build could take a while depending on how many builds are already in the queue - Average time around 15~60 minutes
- If the build was successful, you will see a message stating “Successfully built standalone app: https://expo.io/artifacts/xxxxxxxx-xxxxxxx-xxxxx-xxxxxxxx”
- Download the build file from the expo link
- Launch Xcode
- In the "Xcode" menu choose "Open Developer Tool" -> "Application Loader"
- Drag and drop your downloaded ".ipa" file into the Application Loader and follow the prompts
- Complete the process on App Store Connect
npm install- Increment the version according to version number in the appropriate file:
'app.client.json' || 'app.donor.json'
- Start the desired app to ensure there are no errors:
expo start --config app.client.json || expo start --config app.donor.json
- In your browser choose “Run on iOS simulator”
- Create your desired build of the app to upload:
expo build:android --config app.client.json
OR
expo build:android --config app.donor.json
- Choose "app-bundle" when the console prompts you to choose the build type.
- Once the build finishes on Expo's servers, download the app bundle to your local machine.
- Log in to the BGP's Google Play Console account and create a new release using the console (I am leaving out specific instructions since Google's UI is subject to change, but you should be able to figure it out).
back to top