···3334# Bitdrift API key. If undefined, Bitdrift will be disabled.
35EXPO_PUBLIC_BITDRIFT_API_KEY=
000000
···3334# Bitdrift API key. If undefined, Bitdrift will be disabled.
35EXPO_PUBLIC_BITDRIFT_API_KEY=
36+37+# bapp-config web worker URL
38+BAPP_CONFIG_DEV_URL=
39+40+# Dev-only passthrough value for bapp-config web worker
41+BAPP_CONFIG_DEV_BYPASS_SECRET=
···93 process.env.EXPO_PUBLIC_GCP_PROJECT_ID === undefined
94 ? 0
95 : Number(process.env.EXPO_PUBLIC_GCP_PROJECT_ID)
96+97+/**
98+ * URL for the bapp-config web worker _development_ environment. Can be a
99+ * locally running server, see `env.example` for more.
100+ */
101+export const BAPP_CONFIG_DEV_URL = process.env.BAPP_CONFIG_DEV_URL
102+103+/**
104+ * Dev environment passthrough value for bapp-config web worker. Allows local
105+ * dev access to the web worker running in `development` mode.
106+ */
107+export const BAPP_CONFIG_DEV_BYPASS_SECRET: string =
108+ process.env.BAPP_CONFIG_DEV_BYPASS_SECRET
+2-2
src/lib/currency.ts
···1import React from 'react'
23import {deviceLocales} from '#/locale/deviceLocales'
4-import {useGeolocation} from '#/state/geolocation'
5import {useLanguagePrefs} from '#/state/preferences'
67/**
···275export function useFormatCurrency(
276 options?: Parameters<typeof Intl.NumberFormat>[1],
277) {
278- const {geolocation} = useGeolocation()
279 const {appLanguage} = useLanguagePrefs()
280 return React.useMemo(() => {
281 const locale = deviceLocales.at(0)
···1import React from 'react'
23import {deviceLocales} from '#/locale/deviceLocales'
4+import {useGeolocationStatus} from '#/state/geolocation'
5import {useLanguagePrefs} from '#/state/preferences'
67/**
···275export function useFormatCurrency(
276 options?: Parameters<typeof Intl.NumberFormat>[1],
277) {
278+ const {location: geolocation} = useGeolocationStatus()
279 const {appLanguage} = useLanguagePrefs()
280 return React.useMemo(() => {
281 const locale = deviceLocales.at(0)
+1
src/logger/types.ts
···14 PostSource = 'post-source',
15 AgeAssurance = 'age-assurance',
16 PolicyUpdate = 'policy-update',
01718 /**
19 * METRIC IS FOR INTERNAL USE ONLY, don't create any other loggers using this
···14 PostSource = 'post-source',
15 AgeAssurance = 'age-assurance',
16 PolicyUpdate = 'policy-update',
17+ Geolocation = 'geolocation',
1819 /**
20 * METRIC IS FOR INTERNAL USE ONLY, don't create any other loggers using this
+2-2
src/state/ageAssurance/index.tsx
···11} from '#/state/ageAssurance/types'
12import {useIsAgeAssuranceEnabled} from '#/state/ageAssurance/useIsAgeAssuranceEnabled'
13import {logger} from '#/state/ageAssurance/util'
14-import {useGeolocation} from '#/state/geolocation'
15import {useAgent} from '#/state/session'
1617export const createAgeAssuranceQueryKey = (did: string) =>
···43 */
44export function Provider({children}: {children: React.ReactNode}) {
45 const agent = useAgent()
46- const {geolocation} = useGeolocation()
47 const isAgeAssuranceEnabled = useIsAgeAssuranceEnabled()
48 const getAndRegisterPushToken = useGetAndRegisterPushToken()
49 const [refetchWhilePending, setRefetchWhilePending] = useState(false)
···1+import {useEffect, useRef} from 'react'
2+import * as Location from 'expo-location'
3+4+import {logger} from '#/state/geolocation/logger'
5+import {getDeviceGeolocation} from '#/state/geolocation/util'
6+import {device, useStorage} from '#/storage'
7+8+/**
9+ * Hook to get and sync the device geolocation from the device GPS and store it
10+ * using device storage. If permissions are not granted, it will clear any cached
11+ * storage value.
12+ */
13+export function useSyncedDeviceGeolocation() {
14+ const synced = useRef(false)
15+ const [status] = Location.useForegroundPermissions()
16+ const [deviceGeolocation, setDeviceGeolocation] = useStorage(device, [
17+ 'deviceGeolocation',
18+ ])
19+20+ useEffect(() => {
21+ async function get() {
22+ // no need to set this more than once per session
23+ if (synced.current) return
24+25+ logger.debug('useSyncedDeviceGeolocation: checking perms')
26+27+ if (status?.granted) {
28+ const location = await getDeviceGeolocation()
29+ if (location) {
30+ logger.debug('useSyncedDeviceGeolocation: syncing location')
31+ setDeviceGeolocation(location)
32+ synced.current = true
33+ }
34+ } else {
35+ const hasCachedValue = device.get(['deviceGeolocation']) !== undefined
36+37+ /**
38+ * If we have a cached value, but user has revoked permissions,
39+ * quietly (will take effect lazily) clear this out.
40+ */
41+ if (hasCachedValue) {
42+ logger.debug(
43+ 'useSyncedDeviceGeolocation: clearing cached location, perms revoked',
44+ )
45+ device.set(['deviceGeolocation'], undefined)
46+ }
47+ }
48+ }
49+50+ get().catch(e => {
51+ logger.error('useSyncedDeviceGeolocation: failed to sync', {
52+ safeMessage: e,
53+ })
54+ })
55+ }, [status, setDeviceGeolocation])
56+57+ return [deviceGeolocation, setDeviceGeolocation] as const
58+}