Add region notice to age assurance card (#10439)
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
|
|
||||||
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||||
|
import {regionName} from '#/locale/helpers'
|
||||||
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
|
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
|
||||||
@@ -25,7 +24,38 @@ import {useAgeAssurance} from '#/ageAssurance'
|
|||||||
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_NATIVE} from '#/env'
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useDeviceGeolocationApi} from '#/geolocation'
|
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
|
||||||
|
}
|
||||||
|
|
||||||
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
||||||
const aa = useAgeAssurance()
|
const aa = useAgeAssurance()
|
||||||
@@ -42,15 +72,12 @@ export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
|||||||
|
|
||||||
function Inner({style}: ViewStyleProp & {}) {
|
function Inner({style}: ViewStyleProp & {}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_, i18n} = useLingui()
|
const {t: l, i18n} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const control = useDialogControl()
|
const control = useDialogControl()
|
||||||
const appealControl = Dialog.useDialogControl()
|
const appealControl = Dialog.useDialogControl()
|
||||||
const locationControl = Dialog.useDialogControl()
|
|
||||||
const getTimeAgo = useGetTimeAgo()
|
const getTimeAgo = useGetTimeAgo()
|
||||||
const {gtPhone} = useBreakpoints()
|
const {gtPhone} = useBreakpoints()
|
||||||
const {setDeviceGeolocation} = useDeviceGeolocationApi()
|
|
||||||
const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess()
|
|
||||||
|
|
||||||
const copy = useAgeAssuranceCopy()
|
const copy = useAgeAssuranceCopy()
|
||||||
const aa = useAgeAssurance()
|
const aa = useAgeAssurance()
|
||||||
@@ -97,7 +124,7 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
if one is available in your region. If you have questions or
|
if one is available in your region. If you have questions or
|
||||||
concerns,{' '}
|
concerns,{' '}
|
||||||
<InlineLinkText
|
<InlineLinkText
|
||||||
label={_(msg`Contact our support team`)}
|
label={l`Contact our support team`}
|
||||||
{...createStaticClick(() => {
|
{...createStaticClick(() => {
|
||||||
appealControl.open()
|
appealControl.open()
|
||||||
})}>
|
})}>
|
||||||
@@ -107,47 +134,7 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{IS_NATIVE && (
|
<RegionNotice />
|
||||||
<>
|
|
||||||
<Text style={[a.text_sm, a.leading_snug]}>
|
|
||||||
<Trans>
|
|
||||||
Is your location not accurate?{' '}
|
|
||||||
<InlineLinkText
|
|
||||||
label={_(msg`Confirm your location`)}
|
|
||||||
{...createStaticClick(() => {
|
|
||||||
locationControl.open()
|
|
||||||
})}>
|
|
||||||
Tap here to confirm your location.
|
|
||||||
</InlineLinkText>{' '}
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<DeviceLocationRequestDialog
|
|
||||||
control={locationControl}
|
|
||||||
onLocationAcquired={props => {
|
|
||||||
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',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{isBlocked ? (
|
{isBlocked ? (
|
||||||
@@ -156,7 +143,7 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
You are currently unable to access Bluesky's Age Assurance flow.
|
You are currently unable to access Bluesky's Age Assurance flow.
|
||||||
Please{' '}
|
Please{' '}
|
||||||
<InlineLinkText
|
<InlineLinkText
|
||||||
label={_(msg`Contact our moderation team`)}
|
label={l`Contact our moderation team`}
|
||||||
{...createStaticClick(() => {
|
{...createStaticClick(() => {
|
||||||
appealControl.open()
|
appealControl.open()
|
||||||
ax.metric('ageAssurance:appealDialogOpen', {})
|
ax.metric('ageAssurance:appealDialogOpen', {})
|
||||||
@@ -182,7 +169,7 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
: [a.gap_md],
|
: [a.gap_md],
|
||||||
]}>
|
]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Verify now`)}
|
label={l`Verify now`}
|
||||||
size="small"
|
size="small"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color={hasInitiated ? 'secondary' : 'primary'}
|
color={hasInitiated ? 'secondary' : 'primary'}
|
||||||
@@ -228,3 +215,75 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{IS_NATIVE && (
|
||||||
|
<DeviceLocationRequestDialog
|
||||||
|
control={locationControl}
|
||||||
|
onLocationAcquired={props => {
|
||||||
|
const access = computeAgeAssuranceRegionAccess(props.geolocation)
|
||||||
|
if (access !== aa.Access.Full) {
|
||||||
|
props.disableDialogAction()
|
||||||
|
props.setDialogError(
|
||||||
|
l`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(l`Thanks! You're all set.`, {
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{region && (
|
||||||
|
<Text style={[a.text_sm, a.leading_snug]}>
|
||||||
|
{isGPS ? (
|
||||||
|
<Trans>
|
||||||
|
Based on your device's location, we think you're in{' '}
|
||||||
|
<Text style={[a.text_sm, a.font_bold]}>{region}</Text>. This
|
||||||
|
estimate may be inaccurate if you're using a VPN.
|
||||||
|
</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>
|
||||||
|
Based on your network, we think you're in{' '}
|
||||||
|
<Text style={[a.text_sm, a.font_bold]}>{region}</Text>. This
|
||||||
|
estimate may be inaccurate if you're using a VPN.
|
||||||
|
</Trans>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{IS_NATIVE && (
|
||||||
|
<Text style={[a.text_sm, a.leading_snug]}>
|
||||||
|
<Trans>
|
||||||
|
<InlineLinkText
|
||||||
|
label={l`Confirm your location`}
|
||||||
|
{...createStaticClick(() => {
|
||||||
|
locationControl.open()
|
||||||
|
})}>
|
||||||
|
Tap here to confirm your location.
|
||||||
|
</InlineLinkText>
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user