diff --git a/src/index.ts b/src/index.ts index 1154a59..cfec293 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,18 @@ import { useInterval } from './useInterval/useInterval' import { AsyncState, getAsyncState } from './async-data/asyncState' import { AsyncView } from './async-data/AsyncView' +import { + LocationProvider, + LocationContext, + LocationContextValue, +} from './location-provider/LocationProvider' -export { useInterval, AsyncState, getAsyncState, AsyncView } +export { + useInterval, + AsyncState, + getAsyncState, + AsyncView, + LocationProvider, + LocationContext, + LocationContextValue, +} diff --git a/src/location-provider/LocationProvider.tsx b/src/location-provider/LocationProvider.tsx new file mode 100644 index 0000000..470611b --- /dev/null +++ b/src/location-provider/LocationProvider.tsx @@ -0,0 +1,42 @@ +import React, { useEffect, useState } from 'react' +import { createContext } from 'react' +import { useInterval } from '../index' +import { getCurrentLocation } from './getCurrentLocation' + +export type LocationContextValue = { + location: GeolocationPosition | null +} + +export const LocationContext = createContext({ + location: null, +}) + +export const LocationProvider: React.FC<{ + highAccuracy: boolean + delay: number +}> = ({ highAccuracy, delay, children }) => { + const [location, setLocation] = useState({ + location: null, + }) + + const updateLocation = async () => { + const position = await getCurrentLocation(highAccuracy).catch( + () => location.location + ) + setLocation({ location: position }) + } + + useEffect(() => { + updateLocation() + }, []) + + useInterval(() => { + updateLocation() + }, delay) + + return ( + + {children} + + ) +} diff --git a/src/location-provider/getCurrentLocation.ts b/src/location-provider/getCurrentLocation.ts new file mode 100644 index 0000000..615271b --- /dev/null +++ b/src/location-provider/getCurrentLocation.ts @@ -0,0 +1,23 @@ +const getCurrentLocation = ( + highAccuracy = false +): Promise => { + return new Promise((resolve, reject) => { + const successCallback = (position: GeolocationPosition): void => { + resolve(position) + } + + const errorCallback = (error: GeolocationPositionError) => { + reject(error.message) + } + + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition(successCallback, errorCallback, { + enableHighAccuracy: highAccuracy, + }) + } else { + reject('Geolocation not supported') + } + }) +} + +export { getCurrentLocation }