Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
Use Google Maps on iOS (#39)
Browse files Browse the repository at this point in the history
* frontend/maps: improve location following

The MapView camera now pans to user location through native MapView
APIs, which makes it signifigantly faster and easier to manage.

* frontend/map: do not snap to location if panning

Do not move the camera to the user's location unless the user has
panned around earlier.

* frontend/map: only disable location on gesture

Do not disable automatic location following on android unless the camera panning is actually
caused by a user.

This does not work on iOS, but iOS also has native location following, so it's okay.

* frontend/maps: back with google maps

Apple Maps isn't cooperating. Use this instead to reduce compatibility
requirements. I don't actually fully know if this works.

* frontend: rename .env.sample to .env.template

* frontend/map: cleanup

* frontend: fix lint

* frontend: rename .env.template to sample.env
  • Loading branch information
OxygenCobalt authored Oct 10, 2023
1 parent 57fe926 commit a3bf6df
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 27 deletions.
7 changes: 6 additions & 1 deletion frontend/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@
"**/*"
],
"ios": {
"supportsTablet": true
"supportsTablet": true,
"bundleIdentifier": "org.orecart.app",
"config": {
"googleMapsApiKey": "${process.env.GOOGLE_MAPS_API_KEY_IOS}"
}
},
"android": {
"package": "org.orecart.app",
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
Expand Down
16 changes: 8 additions & 8 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/sample.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GOOGLE_MAPS_API_KEY_IOS=YOUR_API_KEY_HERE
GOOGLE_MAPS_API_KEY_ANDROID=YOUR_API_KEY_HERE
32 changes: 14 additions & 18 deletions frontend/src/components/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import MapView, { type Region } from 'react-native-maps'
import { StyleSheet, type ViewProps, Platform } from 'react-native'
import { StyleSheet, type ViewProps } from 'react-native'
import { type Coordinate } from '../services/location'
import { useRef, useState } from 'react'
import { PROVIDER_GOOGLE } from 'react-native-maps'

const GOLDEN: Region = {
latitude: 39.749675,
longitude: -105.222606,
latitudeDelta: 0.05,
longitudeDelta: 0.05
latitudeDelta: 0.005,
longitudeDelta: 0.005
}

/**
Expand All @@ -17,7 +18,7 @@ export function Map(props: ViewProps): React.ReactElement<ViewProps> {
const [userRegionChanged, setUserRegionChanged] = useState(false)
const mapRef = useRef<MapView>(null)

function followUserLocationAndroid(location: Coordinate | undefined): void {
function panToLocation(location: Coordinate | undefined): void {
// We want to make sure we won't snap back to the user location if they decide to pan around,
// so check if that's the case before panning.
if (location !== undefined && mapRef.current != null && !userRegionChanged) {
Expand All @@ -31,23 +32,18 @@ export function Map(props: ViewProps): React.ReactElement<ViewProps> {
return (
<MapView style={styles.innerMap}
ref={mapRef}
// Use Google Maps everywhere.
provider={PROVIDER_GOOGLE}
initialRegion={GOLDEN}
showsUserLocation={true}
// Android only.
showsMyLocationButton={false}
// followsUserLocation is only available on iOS, so we must reimplement the behavior on Android
// with onUserLocationChange.
followsUserLocation={!userRegionChanged}
onUserLocationChange={Platform.select({
android: event => { followUserLocationAndroid(event.nativeEvent.coordinate) }
})}
onRegionChange={(_region, details) => {
// If the user is panning around, we don't want to snap back to their location.
// However, when we automatically pan to the location as part of the followsUserLocation
// reimplementation on android, this callback would be triggered and disable future pans.
// To prevent this, we check if the user is panning around by checking if the change was a
// gesture. This is not supported on iOS, but since we will only be panning the camera around
// on android, this is fine.
// followsUserLocation is only available on iOS maps, and isn't very cooperative anyway.
// Reimplement it ourselves.
onUserLocationChange={ event => { panToLocation(event.nativeEvent.coordinate) }}
onRegionChange={(_region, details) => {
// If the user is panning around, we don't want to snap back to their location. Note that we
// make sure to exclude camera pans from this to avoid disabling location following at soon
// as it changes.
if (details.isGesture ?? true) {
setUserRegionChanged(true)
}
Expand Down

0 comments on commit a3bf6df

Please sign in to comment.