location.ts

Requests location permissions and retrieves device GPS coordinates

Purpose

This module handles all device location concerns: requesting the appropriate permission scope, resolving the current GPS position, and geocoding a text address into coordinates via the Google Places API.

Its responsibilities include:

  • Requesting ACCESS_FINE_LOCATION on Android or whenInUse/always authorization on iOS
  • Wrapping Geolocation.getCurrentPosition in a Promise with a 15-second timeout
  • Providing a convenience entry point for background location with always scope
  • Providing a separate foreground-only entry point for work area seeding with whenInUse scope
  • Geocoding a free-text address by querying workAreaAddressSearch and resolving the first suggestion

Invariants

Permission Before Position

Both getDeviceLocation and getForegroundLocationForWorkAreaSeed check permission before calling getCurrentPosition.

A denied permission throws Error("Location permission denied") and never attempts a position fix.


iOS Scope Distinction

getDeviceLocation always requests "always" authorization (required for background location used during background fetch).

getForegroundLocationForWorkAreaSeed requests "whenInUse" only, matching the foreground-only use case of seeding a new work area.


Android Geocode Permission

geocodeWorkAreaAddress requests "whenInUse" permission on Android before calling the Places API.

On iOS no additional permission check is performed for geocoding, as location is only used for context in the address search and not required for the API call itself.


Geolocation Options

All getCurrentPosition calls use the same fixed options:

OptionValue
enableHighAccuracytrue
timeout15,000 ms
maximumAge10,000 ms
forceRequestLocationtrue
showLocationDialogtrue

Geocoding Address Validation

geocodeWorkAreaAddress trims the input and throws Error("Enter an address to search.") if it is empty after trimming.

If the Places API returns no suggestions, it throws Error("No matching address found.").


Variants

Address Geocoding Flow

Geocoding uses a two-step session-token flow via workAreaAddressSearch:

  1. searchWorkAreaAddressSuggestions fetches autocomplete predictions
  2. resolveWorkAreaAddressSuggestion fetches full coordinates for the first result

A unique session token is generated per call as ${Date.now()}-${Math.random()}.


Exports

requestLocationPermission(...)

async function requestLocationPermission(iosScope: 'always' | 'whenInUse'): Promise<boolean>

Requests location permission for the given iOS scope. Returns true if granted, false otherwise. Always returns false on unsupported platforms.


getDeviceLocation()

async function getDeviceLocation(): Promise<{ lat: number; lon: number; elev: number }>

Requests always permission and resolves the current GPS position. Throws on denied permission or geolocation error.


getForegroundLocationForWorkAreaSeed()

async function getForegroundLocationForWorkAreaSeed(): Promise<{ lat: number; lon: number }>

Requests whenInUse permission and resolves the current GPS position for work area seeding. Throws on denied permission or geolocation error.


geocodeWorkAreaAddress(...)

async function geocodeWorkAreaAddress(address: string): Promise<{ lat: number; lon: number }>

Geocodes a free-text address to coordinates using the Google Places API. Throws on empty input, permission denial (Android), no results, or API errors.