diff --git a/src/components/LanguageSelect.tsx b/src/components/LanguageSelect.tsx new file mode 100644 index 0000000000..849ab1d752 --- /dev/null +++ b/src/components/LanguageSelect.tsx @@ -0,0 +1,48 @@ +import React from 'react' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {sanitizeAppLanguageSetting} from '#/locale/helpers' +import {APP_LANGUAGES} from '#/locale/languages' +import * as Select from '#/components/Select' + +export function LanguageSelect({ + value, + onChange, +}: { + value: string + onChange: (value: string) => void +}) { + const {_} = useLingui() + + const handleOnChange = React.useCallback( + (value: string) => { + if (!value) return + onChange(sanitizeAppLanguageSetting(value)) + }, + [onChange], + ) + + return ( + + + + + + ( + + + {label} + + )} + items={APP_LANGUAGES.map(l => ({ + label: l.name, + value: l.code2, + }))} + /> + + ) +} diff --git a/src/components/ageAssurance/AgeAssuranceBadge.tsx b/src/components/ageAssurance/AgeAssuranceBadge.tsx new file mode 100644 index 0000000000..79ce3d67f0 --- /dev/null +++ b/src/components/ageAssurance/AgeAssuranceBadge.tsx @@ -0,0 +1,46 @@ +import {View} from 'react-native' +import {Trans} from '@lingui/macro' + +import {atoms as a, select, useTheme} from '#/alf' +import {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield' +import {Text} from '#/components/Typography' + +export function AgeAssuranceBadge() { + const t = useTheme() + + return ( + + + + Age Assurance + + + ) +} diff --git a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx new file mode 100644 index 0000000000..bfaff57905 --- /dev/null +++ b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx @@ -0,0 +1,179 @@ +import {useState} from 'react' +import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {validate as validateEmail} from 'email-validator' + +import {useLanguagePrefs} from '#/state/preferences' +import {useSession} from '#/state/session' +import {atoms as a, useTheme, web} from '#/alf' +import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' +import {urls} from '#/components/ageAssurance/const' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {Divider} from '#/components/Divider' +import * as TextField from '#/components/forms/TextField' +import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '#/components/icons/Envelope' +import {LanguageSelect} from '#/components/LanguageSelect' +import {InlineLinkText} from '#/components/Link' +import {Text} from '#/components/Typography' + +export {useDialogControl} from '#/components/Dialog/context' + +export function AgeAssuranceInitDialog({ + control, +}: { + control: Dialog.DialogControlProps +}) { + const {_} = useLingui() + return ( + + + + + + + + + ) +} + +function Inner() { + const t = useTheme() + const {_} = useLingui() + const {currentAccount} = useSession() + const langPrefs = useLanguagePrefs() + + const [email, setEmail] = useState(currentAccount?.email || '') + const [emailValid, setEmailValid] = useState(validateEmail(email)) + const [language, setLanguage] = useState(langPrefs.appLanguage) + + const onSubmit = async () => { + try { + if (!validateEmail(email)) { + setEmailValid(false) + return + } + } catch (e) {} + } + + return ( + + + + + + Verify your age + + + + + + We use{' '} + + KWS + {' '} + to verify that you’re an adult. When you click "Get an email" + below, Bluesky will share your email address with KWS. + + + + + If KWS cannot use your email address to confirm that you + previously verified your age, you’ll be taken to the KWS website + to provide more details. + + + + This should only take a few minutes. + + + + + + + + + Your email + + + setEmailValid(true)} + onBlur={() => { + setEmailValid(validateEmail(email)) + }} + returnKeyType="done" + autoCapitalize="none" + autoComplete="off" + autoCorrect={false} + onSubmitEditing={onSubmit} + /> + + + + + + Your preferred language + + + + + + + + + + By continuing, you agree to the{' '} + + KWS Terms of Use + {' '} + and acknowledge that KWS will store your verified status alongside + your hashed email address in accordance with the{' '} + + KWS Privacy Policy + + . This means you won’t need to verify again the next time you use + this email for other apps, games, and services powered by KWS + technology. + + + + + ) +} diff --git a/src/components/ageAssurance/AgeAssurancePrompt.tsx b/src/components/ageAssurance/AgeAssurancePrompt.tsx index 326b39da50..828c7cfc63 100644 --- a/src/components/ageAssurance/AgeAssurancePrompt.tsx +++ b/src/components/ageAssurance/AgeAssurancePrompt.tsx @@ -4,120 +4,98 @@ import {useLingui} from '@lingui/react' import {useAgeAssuranceContext} from '#/state/ageAssurance' import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf' +import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' +import { + AgeAssuranceInitDialog, + useDialogControl, +} from '#/components/ageAssurance/AgeAssuranceInitDialog' import {Button, ButtonText} from '#/components/Button' import {Divider} from '#/components/Divider' -import {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield' import {Text} from '#/components/Typography' export function AgeAssurancePrompt({style}: ViewStyleProp & {}) { const t = useTheme() const {_} = useLingui() const {hasInitiated} = useAgeAssuranceContext() + const control = useDialogControl() return hasInitiated ? null : ( - - - - - - - Age Assurance - - - - - You're currently accessing Bluesky from a location that by law - requires you to verify your age prior to accessing certain content and - features. - + <> + - + - - - - Verification takes only a few minutes + + + + + You're currently accessing Bluesky from a location that by law + requires you to verify your age prior to accessing certain content + and features. - + + + + + Verification takes only a few minutes + + + + - + ) } diff --git a/src/components/ageAssurance/const.ts b/src/components/ageAssurance/const.ts new file mode 100644 index 0000000000..3c6b26120a --- /dev/null +++ b/src/components/ageAssurance/const.ts @@ -0,0 +1,5 @@ +export const urls = { + kwsHome: 'https://dev.epicgames.com/docs/kids-web-services', + kwsTermsOfUse: 'https://www.kidswebservices.com/en-US/terms-of-use', + kwsPrivacyPolicy: 'https://www.kidswebservices.com/en-US/privacy-policy', +}