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',
+}