diff options
author | Eric Bailey <git@esb.lol> | 2025-09-04 11:07:12 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-04 11:07:12 -0500 |
commit | f8ae0540a062e6346baf9fbf0481f769fb23a120 (patch) | |
tree | fc888e55258169e8e7246a1c099aab78fc7d9c99 /src/state/geolocation/useSyncedDeviceGeolocation.ts | |
parent | 625b4e61dbf11c1d485bf8e8265df4d5af0c9657 (diff) | |
download | voidsky-f8ae0540a062e6346baf9fbf0481f769fb23a120.tar.zst |
Provide geo-gated users optional GPS fallback for precise location data (#8973)
Diffstat (limited to 'src/state/geolocation/useSyncedDeviceGeolocation.ts')
-rw-r--r-- | src/state/geolocation/useSyncedDeviceGeolocation.ts | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/state/geolocation/useSyncedDeviceGeolocation.ts b/src/state/geolocation/useSyncedDeviceGeolocation.ts new file mode 100644 index 000000000..602f29a30 --- /dev/null +++ b/src/state/geolocation/useSyncedDeviceGeolocation.ts @@ -0,0 +1,58 @@ +import {useEffect, useRef} from 'react' +import * as Location from 'expo-location' + +import {logger} from '#/state/geolocation/logger' +import {getDeviceGeolocation} from '#/state/geolocation/util' +import {device, useStorage} from '#/storage' + +/** + * Hook to get and sync the device geolocation from the device GPS and store it + * using device storage. If permissions are not granted, it will clear any cached + * storage value. + */ +export function useSyncedDeviceGeolocation() { + const synced = useRef(false) + const [status] = Location.useForegroundPermissions() + const [deviceGeolocation, setDeviceGeolocation] = useStorage(device, [ + 'deviceGeolocation', + ]) + + useEffect(() => { + async function get() { + // no need to set this more than once per session + if (synced.current) return + + logger.debug('useSyncedDeviceGeolocation: checking perms') + + if (status?.granted) { + const location = await getDeviceGeolocation() + if (location) { + logger.debug('useSyncedDeviceGeolocation: syncing location') + setDeviceGeolocation(location) + synced.current = true + } + } else { + const hasCachedValue = device.get(['deviceGeolocation']) !== undefined + + /** + * If we have a cached value, but user has revoked permissions, + * quietly (will take effect lazily) clear this out. + */ + if (hasCachedValue) { + logger.debug( + 'useSyncedDeviceGeolocation: clearing cached location, perms revoked', + ) + device.set(['deviceGeolocation'], undefined) + } + } + } + + get().catch(e => { + logger.error('useSyncedDeviceGeolocation: failed to sync', { + safeMessage: e, + }) + }) + }, [status, setDeviceGeolocation]) + + return [deviceGeolocation, setDeviceGeolocation] as const +} |