diff --git a/src/ageAssurance/components/NoAccessScreen.tsx b/src/ageAssurance/components/NoAccessScreen.tsx
index 6e323b7f03..1f50fa9821 100644
--- a/src/ageAssurance/components/NoAccessScreen.tsx
+++ b/src/ageAssurance/components/NoAccessScreen.tsx
@@ -43,19 +43,20 @@ import {logger} from '#/ageAssurance/logger'
import {unsafeGetAndComputeAgeAssurance} from '#/ageAssurance/state'
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
import {
+ createGeolocationString,
getAgeAssuranceDataFromDeviceSignals,
isLegacyBirthdateBug,
useAgeAssuranceRegionConfig,
} from '#/ageAssurance/util'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE, IS_WEB} from '#/env'
-import {useDeviceGeolocationApi} from '#/geolocation'
+import {useDeviceGeolocationApi, useGeolocation} from '#/geolocation'
const textStyles = [a.text_md, a.leading_snug]
export function NoAccessScreen() {
const t = useTheme()
- const {_} = useLingui()
+ const {_, i18n} = useLingui()
const ax = useAnalytics()
const {gtPhone} = useBreakpoints()
const insets = useSafeAreaInsets()
@@ -67,6 +68,10 @@ export function NoAccessScreen() {
const isBirthdateUpdateAllowed = useIsBirthdateUpdateAllowed()
const {logoutCurrentAccount} = useSessionApi()
const createSupportLink = useCreateSupportLink()
+ const geolocation = useGeolocation()
+ const {setDeviceGeolocation} = useDeviceGeolocationApi()
+ const locationControl = Dialog.useDialogControl()
+ const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess()
const aa = useAgeAssurance()
const isBlocked = aa.state.status === aa.Status.Blocked
@@ -74,6 +79,8 @@ export function NoAccessScreen() {
const hasDeclaredAge = aa.flags.hasDeclaredAge
const canUpdateBirthday =
isBirthdateUpdateAllowed || isLegacyBirthdateBug(metadata?.birthdate || '')
+ const geolocationString = createGeolocationString(geolocation, i18n.locale)
+ const isUsingGPS = !!geolocation.deviceGeolocation?.countryCode && IS_NATIVE
useEffect(() => {
// just counting overall hits here
@@ -189,6 +196,78 @@ export function NoAccessScreen() {
+ {region && (
+
+ {isUsingGPS ? (
+
+ Based on your device's location, we think you're
+ in{' '}
+
+ {geolocationString}
+
+ .
+
+ ) : (
+ <>
+
+ Based on your network, we think you're in{' '}
+
+ {geolocationString}
+
+ . This estimate may be inaccurate if you're
+ using a VPN.
+ {' '}
+ {IS_NATIVE && (
+ <>
+
+ You can also{' '}
+ {
+ locationControl.open()
+ })}
+ style={[textStyles]}>
+ tap here to update your location with GPS.
+
+
+
+ {
+ const access =
+ computeAgeAssuranceRegionAccess(
+ props.geolocation,
+ )
+ if (access !== aa.Access.Full) {
+ props.disableDialogAction()
+ props.setDialogError(
+ _(
+ msg`We're sorry, but based on your device's location, you are currently located in a region that requires age assurance.`,
+ ),
+ )
+ } else {
+ props.closeDialog(() => {
+ // set this after close!
+ setDeviceGeolocation(
+ props.geolocation,
+ )
+ Toast.show(
+ _(msg`Thanks! You're all set.`),
+ {
+ type: 'success',
+ },
+ )
+ })
+ }
+ }}
+ />
+ >
+ )}
+ >
+ )}
+
+ )}
+
{!aa.flags.isOverRegionMinAccessAge && (
@@ -312,10 +391,7 @@ function AccessSection() {
const ax = useAnalytics()
const control = useDialogControl()
const appealControl = Dialog.useDialogControl()
- const locationControl = Dialog.useDialogControl()
const getTimeAgo = useGetTimeAgo()
- const {setDeviceGeolocation} = useDeviceGeolocationApi()
- const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess()
const {currentAccount} = useSession()
const region = useAgeAssuranceRegionConfig()
@@ -505,50 +581,6 @@ function AccessSection() {
>
)}
-
-
- {IS_NATIVE && (
- <>
-
-
- Is your location not accurate?{' '}
- {
- locationControl.open()
- })}>
- Tap here to update your location with GPS.
-
-
-
-
- {
- const access = computeAgeAssuranceRegionAccess(
- props.geolocation,
- )
- if (access !== aa.Access.Full) {
- props.disableDialogAction()
- props.setDialogError(
- _(
- msg`We're sorry, but based on your device's location, you are currently located in a region that requires age assurance.`,
- ),
- )
- } else {
- props.closeDialog(() => {
- // set this after close!
- setDeviceGeolocation(props.geolocation)
- Toast.show(_(msg`Thanks! You're all set.`), {
- type: 'success',
- })
- })
- }
- }}
- />
- >
- )}
-
>
)
diff --git a/src/ageAssurance/debug.ts b/src/ageAssurance/debug.ts
index 49a2269351..84c20a31c0 100644
--- a/src/ageAssurance/debug.ts
+++ b/src/ageAssurance/debug.ts
@@ -9,24 +9,22 @@ import {type OtherRequiredData} from '#/ageAssurance/data'
import {IS_DEV, IS_E2E} from '#/env'
import {type Geolocation} from '#/geolocation'
-export const enabled = (IS_DEV && false) || IS_E2E
+export const enabled = (IS_DEV && true) || IS_E2E
export const geolocation: Geolocation | undefined = enabled
? {
- countryCode: 'AA',
- regionCode: undefined,
+ countryCode: 'US',
+ regionCode: 'TX',
}
: undefined
-const deviceGeolocationEnabled = false || IS_E2E
-export const deviceGeolocation: Geolocation | undefined =
- enabled && deviceGeolocationEnabled
- ? {
- countryCode: 'AA',
- regionCode: undefined,
- ...geolocation,
- }
- : undefined
+export const deviceGeolocation: Geolocation | undefined = enabled
+ ? {
+ countryCode: 'AA',
+ regionCode: undefined,
+ ...geolocation,
+ }
+ : undefined
export const otherRequiredData: OtherRequiredData = {
birthdate: new Date(2000, 12, 1).toISOString(),
diff --git a/src/ageAssurance/util.ts b/src/ageAssurance/util.ts
index 955e4c129c..b746b45c7c 100644
--- a/src/ageAssurance/util.ts
+++ b/src/ageAssurance/util.ts
@@ -7,6 +7,7 @@ import {
} from '@atproto/api'
import {getAge} from '#/lib/strings/time'
+import {regionName} from '#/locale/helpers'
import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/const'
import {
DEVICE_SIGNALS_SUPPORTED,
@@ -21,6 +22,7 @@ import {
type AgeAssuranceState,
} from '#/ageAssurance/types'
import {type Geolocation, useGeolocation} from '#/geolocation'
+import {USRegionNameToRegionCode} from '#/geolocation/util'
/**
* Get age assurance region config based on geolocation, with fallback to
@@ -206,3 +208,27 @@ export function computeAgeAssuranceFlags({
allowsDeviceVerification,
}
}
+
+const USRegionCodeToRegionName: {[regionCode: string]: string} =
+ Object.fromEntries(
+ Object.entries(USRegionNameToRegionCode).map(([name, code]) => [
+ code,
+ name,
+ ]),
+ )
+export function createGeolocationString(
+ geolocation: Geolocation,
+ appLang: string,
+): string | undefined {
+ const {countryCode, regionCode} = geolocation
+ if (!countryCode) return undefined
+ const country = regionName(countryCode, appLang)
+ // If `regionName` couldn't resolve a real name and fell through to the raw
+ // code, we'd rather show nothing than a bare ISO code in the prose.
+ if (country === countryCode) return undefined
+ if (regionCode && countryCode === 'US') {
+ const state = USRegionCodeToRegionName[regionCode]
+ if (state) return `${state}, ${country}`
+ }
+ return country
+}
diff --git a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx
index 3f4f1f98f6..8703390d55 100644
--- a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx
+++ b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx
@@ -2,7 +2,6 @@ import {View} from 'react-native'
import {Trans, useLingui} from '@lingui/react/macro'
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
-import {regionName} from '#/locale/helpers'
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
@@ -22,40 +21,10 @@ import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {useAgeAssurance} from '#/ageAssurance'
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
+import {createGeolocationString} from '#/ageAssurance/util'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE} from '#/env'
-import {
- type Geolocation,
- useDeviceGeolocationApi,
- useGeolocation,
-} from '#/geolocation'
-import {USRegionNameToRegionCode} from '#/geolocation/util'
-import {device, useStorage} from '#/storage'
-
-const USRegionCodeToRegionName: {[regionCode: string]: string} =
- Object.fromEntries(
- Object.entries(USRegionNameToRegionCode).map(([name, code]) => [
- code,
- name,
- ]),
- )
-
-function formatRegion(
- geolocation: Geolocation,
- appLang: string,
-): string | undefined {
- const {countryCode, regionCode} = geolocation
- if (!countryCode) return undefined
- const country = regionName(countryCode, appLang)
- // If `regionName` couldn't resolve a real name and fell through to the raw
- // code, we'd rather show nothing than a bare ISO code in the prose.
- if (country === countryCode) return undefined
- if (regionCode && countryCode === 'US') {
- const state = USRegionCodeToRegionName[regionCode]
- if (state) return `${state}, ${country}`
- }
- return country
-}
+import {useDeviceGeolocationApi, useGeolocation} from '#/geolocation'
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
const aa = useAgeAssurance()
@@ -220,13 +189,12 @@ function RegionNotice() {
const {t: l, i18n} = useLingui()
const aa = useAgeAssurance()
const geolocation = useGeolocation()
- const [deviceGeolocation] = useStorage(device, ['deviceGeolocation'])
const {setDeviceGeolocation} = useDeviceGeolocationApi()
const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess()
const locationControl = Dialog.useDialogControl()
- const region = formatRegion(geolocation, i18n.locale)
- const isGPS = !!deviceGeolocation?.countryCode && IS_NATIVE
+ const region = createGeolocationString(geolocation, i18n.locale)
+ const isGPS = !!geolocation.deviceGeolocation?.countryCode && IS_NATIVE
return (
<>
@@ -258,8 +226,7 @@ function RegionNotice() {
{isGPS ? (
Based on your device's location, we think you're in{' '}
- {region}. This
- estimate may be inaccurate if you're using a VPN.
+ {region}.
) : (
diff --git a/src/geolocation/index.tsx b/src/geolocation/index.tsx
index c9dc0cb1ed..37d9d4b155 100644
--- a/src/geolocation/index.tsx
+++ b/src/geolocation/index.tsx
@@ -22,6 +22,8 @@ export * from '#/geolocation/types'
const GeolocationContext = createContext({
countryCode: undefined,
regionCode: undefined,
+ serviceGeolocation: undefined,
+ deviceGeolocation: undefined,
})
const DeviceGeolocationAPIContext = createContext<{
@@ -44,7 +46,17 @@ export function Provider({children}: {children: ReactNode}) {
'deviceGeolocation',
])
const geolocation = useMemo(() => {
- return mergeGeolocations(deviceGeolocation, geolocationService)
+ 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(() => {
diff --git a/src/geolocation/types.ts b/src/geolocation/types.ts
index 80848730c9..979b4dd742 100644
--- a/src/geolocation/types.ts
+++ b/src/geolocation/types.ts
@@ -1,4 +1,6 @@
export type Geolocation = {
countryCode: string | undefined
regionCode: string | undefined
+ serviceGeolocation?: Geolocation
+ deviceGeolocation?: Geolocation
}