Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions app/utils/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ export const areCoordsInSanFrancisco = (coords: GeoCoordinates): boolean => {
);
};

/**
* Thrown by getLocationBrowser when the browser successfully returns a real
* location, but it falls outside the bounds we support. This is distinct
* from other rejection reasons (permission denied, unsupported browser,
* timeout, etc.) because it means we already have a real answer -- there's
* no reason to believe Google's (IP-based, less precise) Geolocation API
* would give a meaningfully different result, so callers can skip that
* billed API call and fall straight back to the default location.
*/
export class OutOfBoundsLocationError extends Error {}

/**
* Get location via HTML5 Geolocation API.
*/
Expand All @@ -41,7 +52,7 @@ export const getLocationBrowser = () =>
} else {
const msg = `User location out of bounds: ${coords.lat},${coords.lng}`;
console.log(msg); // eslint-disable-line no-console
reject(msg);
reject(new OutOfBoundsLocationError(msg));
}
},
(error) => {
Expand Down Expand Up @@ -134,11 +145,22 @@ export const useDefaultSanFranciscoLocation = () =>
* inaccurate geolocation results, but this should be removed if more locations
* are added.
*
* @todo if getLocationBrowser is outside SF, errs and tries to load google as well. Fix
* @returns A Promise of a location, which is either an object with `lat` and
* `lng` properties or an error if location is unavaible or out of bounds.
*/
export const getLocation = () =>
getLocationBrowser()
.catch(() => getLocationGoogle())
.catch(() => useDefaultSanFranciscoLocation());
getLocationBrowser().catch((reason) => {
if (reason instanceof OutOfBoundsLocationError) {
// The browser gave us a real, precise location -- it's just outside
// the area we support. Calling Google's (IP-based, less precise)
// Geolocation API here is very unlikely to give a meaningfully
// different answer, so skip that billed call and go straight to the
// default location.
return useDefaultSanFranciscoLocation();
}

// Any other rejection reason (permission denied, unsupported browser,
// timeout, etc.) means we don't have a real location yet, so it's
// still worth trying Google's Geolocation API as a fallback.
return getLocationGoogle().catch(() => useDefaultSanFranciscoLocation());
});
Loading