From 094c39b7a25d638cad9ffe7627b72e9fe067eba5 Mon Sep 17 00:00:00 2001 From: vineyardbovines Date: Thu, 7 May 2026 12:22:41 -0400 Subject: [PATCH] copy update --- .../ageAssurance/AgeAssuranceAccountCard.tsx | 534 ++++++++++-------- 1 file changed, 290 insertions(+), 244 deletions(-) diff --git a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx index 9c1555ad17..ab04602224 100644 --- a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx +++ b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx @@ -9,8 +9,8 @@ import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAp import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' import {AgeAssuranceConfigUnavailableError} from '#/components/ageAssurance/AgeAssuranceErrors' import { - AgeAssuranceInitDialog, - useDialogControl, + AgeAssuranceInitDialog, + useDialogControl, } from '#/components/ageAssurance/AgeAssuranceInitDialog' import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy' import {Button, ButtonText} from '#/components/Button' @@ -25,271 +25,317 @@ import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAs import {useAnalytics} from '#/analytics' import {IS_NATIVE} from '#/env' import { - type Geolocation, - useDeviceGeolocationApi, - useGeolocation, + type Geolocation, + useDeviceGeolocationApi, + useGeolocation, } from '#/geolocation' import {USRegionNameToRegionCode} from '#/geolocation/util' import {device, useStorage} from '#/storage' +// DEBUG: remove before merging. Forces the card to render with a fake region +// so the RegionNotice copy can be previewed/screenshotted locally. +const DEBUG_FORCE_REGION_PREVIEW = true +// DEBUG: when previewing, set true to render the GPS copy variant instead of +// the network copy variant. +const DEBUG_FORCE_GPS = true + const USRegionCodeToRegionName: {[regionCode: string]: string} = - Object.fromEntries( - Object.entries(USRegionNameToRegionCode).map(([name, code]) => [ - code, - name, - ]), - ) + Object.fromEntries( + Object.entries(USRegionNameToRegionCode).map(([name, code]) => [ + code, + name, + ]), + ) function formatRegion( - geolocation: Geolocation, - appLang: string, + 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 + 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 & {}) { - const aa = useAgeAssurance() - if (aa.state.access === aa.Access.Full) return null - if (aa.state.error === 'config') { - return ( - - - - ) - } - return + const aa = useAgeAssurance() + if (!DEBUG_FORCE_REGION_PREVIEW && aa.state.access === aa.Access.Full) + return null + if (aa.state.error === 'config') { + return ( + + + + ) + } + return } function Inner({style}: ViewStyleProp & {}) { - const t = useTheme() - const {t: l, i18n} = useLingui() - const ax = useAnalytics() - const control = useDialogControl() - const appealControl = Dialog.useDialogControl() - const getTimeAgo = useGetTimeAgo() - const {gtPhone} = useBreakpoints() + const t = useTheme() + const {t: l, i18n} = useLingui() + const ax = useAnalytics() + const control = useDialogControl() + const appealControl = Dialog.useDialogControl() + const getTimeAgo = useGetTimeAgo() + const {gtPhone} = useBreakpoints() - const copy = useAgeAssuranceCopy() - const aa = useAgeAssurance() - const {status, lastInitiatedAt} = aa.state - const isBlocked = status === aa.Status.Blocked - const hasInitiated = !!lastInitiatedAt - const hasCompletedFlow = status === aa.Status.Assured - const timeAgo = lastInitiatedAt - ? getTimeAgo(lastInitiatedAt, new Date()) - : null - const diff = lastInitiatedAt - ? dateDiff(lastInitiatedAt, new Date(), 'down') - : null + const copy = useAgeAssuranceCopy() + const aa = useAgeAssurance() + const {status, lastInitiatedAt} = aa.state + const isBlocked = status === aa.Status.Blocked + const hasInitiated = !!lastInitiatedAt + const hasCompletedFlow = status === aa.Status.Assured + const timeAgo = lastInitiatedAt + ? getTimeAgo(lastInitiatedAt, new Date()) + : null + const diff = lastInitiatedAt + ? dateDiff(lastInitiatedAt, new Date(), 'down') + : null - return ( - <> - - + return ( + <> + + - - - - - + + + + + + + + + + + {copy.notice} + + {hasCompletedFlow && ( + + + If you are 18 years of age or older and want + to try again, click the button below and use + a different verification method if one is + available in your region. If you have + questions or concerns,{' '} + { + appealControl.open() + })}> + our support team can help. + + + + )} + + + + + {isBlocked ? ( + + + You are currently unable to access Bluesky's Age + Assurance flow. Please{' '} + { + appealControl.open() + ax.metric( + 'ageAssurance:appealDialogOpen', + {}, + ) + })}> + contact our moderation team + {' '} + if you believe this is an error. + + + ) : ( + <> + + + + + {lastInitiatedAt && timeAgo && diff ? ( + + {diff.value === 0 ? ( + + Last initiated just now + + ) : ( + + Last initiated {timeAgo} ago + + )} + + ) : ( + + + Age assurance only takes a few + minutes + + + )} + + + )} + - - - - {copy.notice} - {hasCompletedFlow && ( - - - If you are 18 years of age or older and want to try again, - click the button below and use a different verification method - if one is available in your region. If you have questions or - concerns,{' '} - { - appealControl.open() - })}> - our support team can help. - - - - )} - - - - - {isBlocked ? ( - - - You are currently unable to access Bluesky's Age Assurance flow. - Please{' '} - { - appealControl.open() - ax.metric('ageAssurance:appealDialogOpen', {}) - })}> - contact our moderation team - {' '} - if you believe this is an error. - - - ) : ( - <> - - - - - {lastInitiatedAt && timeAgo && diff ? ( - - {diff.value === 0 ? ( - Last initiated just now - ) : ( - Last initiated {timeAgo} ago - )} - - ) : ( - - Age assurance only takes a few minutes - - )} - - - )} - - - - ) + + ) } 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 {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 + const region = DEBUG_FORCE_REGION_PREVIEW + ? 'Switzerland' + : formatRegion(geolocation, i18n.locale) + const isGPS = DEBUG_FORCE_REGION_PREVIEW + ? DEBUG_FORCE_GPS + : !!deviceGeolocation?.countryCode - return ( - <> - {IS_NATIVE && ( - { - 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', - }) - }) - } - }} - /> - )} + return ( + <> + {IS_NATIVE && ( + { + 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 && ( - - {isGPS ? ( - - Based on your device's location, we think you're in{' '} - {region}. Some - features are limited because of regional age laws. - - ) : ( - - Based on your network, we think you're in{' '} - {region}. Some - features are limited because of regional age laws. - - )} - - )} + {region && ( + + {isGPS ? ( + + Based on your device's location, we think you're in{' '} + + {region} + + . This estimate may be inaccurate if you're using a + VPN. + + ) : ( + + Based on your network, we think you're in{' '} + + {region} + + . This estimate may be inaccurate if you're using a + VPN. + + )} + + )} - {region && !isGPS && ( - - This estimate may be inaccurate if you're using a VPN. - - )} - - {IS_NATIVE && ( - - - { - locationControl.open() - })}> - Tap here to confirm your location. - - - - )} - - ) + {IS_NATIVE && ( + + + { + locationControl.open() + })}> + Tap here to confirm your location. + + + + )} + + ) }