Files
bsky-social-app/src/geolocation/index.tsx
Eric Bailey 954268a4b6 [AAv2] Integrate on-device APIs (#9564)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:15:30 -05:00

81 lines
2.4 KiB
TypeScript

import {
createContext,
type ReactNode,
useContext,
useEffect,
useMemo,
} from 'react'
import {useSyncDeviceGeolocationOnStartup} from '#/geolocation/device'
import {useGeolocationServiceResponse} from '#/geolocation/service'
import {type Geolocation} from '#/geolocation/types'
import {mergeGeolocations} from '#/geolocation/util'
import {device, useStorage} from '#/storage'
export {
useIsDeviceGeolocationGranted,
useRequestDeviceGeolocation,
} from '#/geolocation/device'
export {resolve} from '#/geolocation/service'
export * from '#/geolocation/types'
const GeolocationContext = createContext<Geolocation>({
countryCode: undefined,
regionCode: undefined,
serviceGeolocation: undefined,
deviceGeolocation: undefined,
})
const DeviceGeolocationAPIContext = createContext<{
setDeviceGeolocation(deviceGeolocation: Geolocation): void
}>({
setDeviceGeolocation: () => {},
})
export function useGeolocation() {
return useContext(GeolocationContext)
}
export function useDeviceGeolocationApi() {
return useContext(DeviceGeolocationAPIContext)
}
export function Provider({children}: {children: ReactNode}) {
const geolocationService = useGeolocationServiceResponse()
const [deviceGeolocation, setDeviceGeolocation] = useStorage(device, [
'deviceGeolocation',
])
const geolocation = useMemo(() => {
const geo = mergeGeolocations(deviceGeolocation, geolocationService)
// create new objects to avoid cyclical references
geo.serviceGeolocation = {
countryCode: geolocationService?.countryCode,
regionCode: geolocationService?.regionCode,
}
geo.deviceGeolocation = {
countryCode: deviceGeolocation?.countryCode,
regionCode: deviceGeolocation?.regionCode,
}
return geo
}, [deviceGeolocation, geolocationService])
useEffect(() => {
/**
* Save this for out-of-band-reads during future cold starts of the app.
* Needs to be available for the data prefetching we do on boot.
*/
device.set(['mergedGeolocation'], geolocation)
}, [geolocation])
useSyncDeviceGeolocationOnStartup(setDeviceGeolocation)
return (
<GeolocationContext.Provider value={geolocation}>
<DeviceGeolocationAPIContext.Provider
value={useMemo(() => ({setDeviceGeolocation}), [setDeviceGeolocation])}>
{children}
</DeviceGeolocationAPIContext.Provider>
</GeolocationContext.Provider>
)
}