Dropanon

Peter Margaritoff
React Native Development
4 min readJan 16, 2017

--

Why I built a React Native App

Dropanon was born when I was looking for a way to tackle two goals:

  1. Build an app from the ground up in React Native
  2. Get an app through the Apple App Store submission process

The product itself was born out of my personal affinity for online anonymity, and my cofounders vehement dislike of people posting Yelp reviews to build their online brand.

What is Dropanon?

Dropanon is a location based, anonymous messaging application currently available on the iOS app store (Android coming soon). A user can drop words, emojis or links at their location. Each drop gets a radius of 75 meters and can only be read within that radius. Think of it like graffiti.

alpha/beta builds had different drop radii, thus the differently sized circles. for v1 we decided on a 75 meter radius. drops can only be read if the user is inside one of the circles.

Drops are visualized on a map view and are read in a feed/list view. The map will only visualize drops up to 500 meters away from the users. This limit is imposed to limit the number of requests the client needs to make and to encourage the user to walk around and explore.

Every drop is anonymous. The only unique identifier stored is a RFC4122 v1 unique user ID (using React Native UUID1). This UUID is used only to allow users to flag or block others (this is an App Store requirement).

Currently, drops will live forever and are presented to the user in chronological order. Some of the feedback we have already received is to make drops ephemeral — have them disappear after a certain number of minutes, hours or days. This is something we might do in the future but for now, your drops will live on.

How

Project structure

Dropanon is built using React Native and Reflux. Persistence is handled by Firebase (and GeoFire for geo queries). The basic app flow, from startup is as follows:

  1. Initialize application and load views. This is handled in App.js which is the top level React component. A lot of stuff happens here on componentDidMount() such as checking to see whether or not the user has been onboarded or whether or not the right permissions have been granted (location while app is in use). All of the Reflux Stores are also initialized here and listeners are attached.
  2. If permissions are missing, the user has not been onboarded or some other problem occurs, we handle it appropriately.
  3. Reflux Stores which were initialized by App.js start handling their respective tasks. These are broken out logically into: ErrorStore, FirebaseStore, GeoStore and TimerStore.

ErrorStore.js

Errors!

ErrorStore is in charge of, yup, errors. Any caught error is passed to it are passed back to App.js which then displays an error bar across the top telling the user what went wrong. Banners can be dismissed by tapping them.

FirebaseStore.js

All drops are saved to and read from one of Firebase’s realtime databases. Firebase has allowed us to do away with writing our own backend and we very quickly had working prototypes up and running. There are a few challenges that we encountered but overall I think we were quicker with Firebase than had we rolled our own backend (https://dropanon.com is also hosted on Firebase).

FirebaseStore initializes a Firebase instance and uses their signInAnonymously() function to create a user (for read/write permissions). All database interactions go through this store. They are as follows:

Settings
  1. onFlagDrop() — a user has flagged a drop. FirebaseStore will look up the post by postId and set its flagged property to true. If a user has chosen to hide flagged drops from the settings menu, these drops will no longer be shown to them.
  2. onFetchFeed() — takes a coordinates parameter and uses a GeoFire geoquery to fetch the correct drops for the current location. Returned drops are then bucketed into: dropsToDisplay if: distance <= dropRadius and dropsToMap if distance <= 500.
  3. onDropSubmit() — takes a drop object, does some checks to make sure it’s all there and pushes it to the database.

FirebaseStore does a few other things too like set and/or fetch permissions settings which were saved on the device.

GeoStore.js

GeoStore handles all geolocation related tasks. On initialization the current location is fetched and passed to App.js. A listener is then attached with a distanceFilter of 10 meters so we get the latest position if the distance between the current location and the last location is greater than 10 meters.

TimerStore.js

TimerStore is used to keep track of time. We restrict each user to 3 drops every 5 minutes. Nothing very fancy goes on in here.

Challenges

  • GeoFire does not let you query by location in the traditional sense. Instead it fires events on key_entered. This means that we can’t limit or paginate results on the server and have to do it on the client instead. For now, this is fine because the total number of drops downloaded per device is relatively small but this might become an issue in the future if usage picks up.
  • React Native debugging can be difficult and/or time consuming.
  • Single thread nature of JavaScript can lead to performance issues. We did not encounter anything grave here yet and most issues were alleviated by using Interactionmanager.runAfterInteractions(() => {...});

--

--