With the local infrastructure completed in Episode 1, it is time to add the main map to Geonotes.
📱 Adding a map to the main screen
On the client, the first step was to add a map to the main screen. Fortunately, Expo supports a library out of the box: React Native Maps.
With this library, a MapKit
instance is created on iOS, while Android uses Google Maps. The props interface is the same across both platforms.
One thing I really like about RNM is that it has built-in support for requesting permissions. Originally I thought I'd do it with Expo Location but so far I haven't felt the need to switch to a dedicated location library.
RNM is able to request the current location of the user, and then display it directly on the map. Adding the followsUserLocation
prop and blocking the various movements, I was able to center the map on the user and update the visible region when they move.
This also allows me to listen to the onRegionChangeComplete
event and extract the current location.
In order not to perform too many queries against the database, the current location is only updated when the user moves more than a given distance from the last location.
🌍 Measuring the distance client-side and in queries
To measure the distance between the last and the current location of the user, I decided to use the "Equirectangular approximation" that should have plenty of precision over relatively small distances.
The implementation is as follows Source:
const R = 6371e3; // Earth's radius
const lat1 = (location1.latitude * Math.PI) / 180;
const lat2 = (location2.latitude * Math.PI) / 180;
const lon1 = (location1.longitude * Math.PI) / 180;
const lon2 = (location2.longitude * Math.PI) / 180;
const deltaLat = lat2 - lat1;
const deltaLon = lon2 - lon1;
const x = deltaLon * Math.cos((lat1 + lat2) / 2);
const y = deltaLat;
return Math.sqrt(x * x + y * y) * R;
On the server, however, I needed something more battle-tested and performant.
Since Hasura uses PostgreSQL as a database, I decided to use the PostGIS extension. Another option I have considered is the GeoHash algorithm, but PostGIS has a much better integration with the current stack.
With PostGIS enabled, I set the "location" column in the "note" table as geography
, which allows me to perform queries like this Source:
query Notes($latitude: Float!, $longitude: Float!, $distance: Float! = 100) {
notes: note(
where: {
location: {
_st_d_within: {
distance: $distance
from: { type: "Point", coordinates: [$longitude, $latitude] }
}
}
}
) {
id
content
location
}
}
⭐️ The result
Ultimately, I was able to query notes in a range around the user, and have those notes update as the user moved.
First location | Second location |
---|---|
🚧 Next steps
Now it is time to work a bit on the presentation of the various notes. My current plan is to show a small callout when a note is tapped, and then display a bottom sheet with the full information / actions.
🎙 How to follow the project
I'll be posting updates throughout the development process and as I learn new thing regarding development, design, and marketing.
If you'd like to have even more real-time updates you can
- Follow me on Twitter @emilioschepis
- Checkout the public GitHub app repository and backend repository
Top comments (0)