Move Takendown and Deactivated screens out to the shell alongside AA

This commit is contained in:
Eric Bailey
2025-12-11 11:44:24 -06:00
parent 506bad83ba
commit 16413f9dbb
6 changed files with 152 additions and 149 deletions
+106 -102
View File
@@ -114,123 +114,127 @@ export function NoAccessScreen() {
return ( return (
<> <>
<ScrollView <View style={[a.util_screen_outer, a.flex_1]}>
contentContainerStyle={[ <ScrollView
a.px_2xl, contentContainerStyle={[
{ a.px_2xl,
paddingTop: isWeb ? a.p_5xl.padding : insets.top + a.p_2xl.padding,
paddingBottom: 100,
},
]}>
<View
style={[
a.mx_auto,
a.w_full,
web({
maxWidth: 380,
paddingTop: gtPhone ? '8vh' : undefined,
}),
{ {
gap: 32, paddingTop: isWeb
? a.p_5xl.padding
: insets.top + a.p_2xl.padding,
paddingBottom: 100,
}, },
]}> ]}>
<View style={[a.align_start]}> <View
<AgeAssuranceBadge /> style={[
</View> a.mx_auto,
a.w_full,
web({
maxWidth: 380,
paddingTop: gtPhone ? '8vh' : undefined,
}),
{
gap: 32,
},
]}>
<View style={[a.align_start]}>
<AgeAssuranceBadge />
</View>
{hasDeclaredAge ? ( {hasDeclaredAge ? (
<> <>
{isAARegion ? ( {isAARegion ? (
<> <>
<View style={[a.gap_lg]}>
<Text style={[textStyles]}>
<Trans>Hey there!</Trans>
</Text>
<Text style={[textStyles]}>
<Trans>
You are accessing Bluesky from a region that legally
requires us to verify your age before allowing you to
access the app.
</Trans>
</Text>
{!isBlocked && birthdateUpdateText}
</View>
<AccessSection />
</>
) : (
<View style={[a.gap_lg]}> <View style={[a.gap_lg]}>
<Text style={[textStyles]}>
<Trans>Hey there!</Trans>
</Text>
<Text style={[textStyles]}> <Text style={[textStyles]}>
<Trans> <Trans>
You are accessing Bluesky from a region that legally Unfortunately, the birthdate you have saved to your
requires us to verify your age before allowing you to profile makes you too young to access Bluesky.
access the app.
</Trans> </Trans>
</Text> </Text>
{!isBlocked && birthdateUpdateText} {birthdateUpdateText}
</View> </View>
)}
<AccessSection /> </>
</> ) : (
) : ( <View style={[a.gap_lg]}>
<View style={[a.gap_lg]}> <Text style={[textStyles]}>
<Text style={[textStyles]}> <Trans>Hi there!</Trans>
<Trans> </Text>
Unfortunately, the birthdate you have saved to your <Text style={[textStyles]}>
profile makes you too young to access Bluesky.
</Trans>
</Text>
{birthdateUpdateText}
</View>
)}
</>
) : (
<View style={[a.gap_lg]}>
<Text style={[textStyles]}>
<Trans>Hi there!</Trans>
</Text>
<Text style={[textStyles]}>
<Trans>
In order to provide an age-appropriate experience, we need to
know your birthdate. This is a one-time thing, and your data
will be kept private.
</Trans>
</Text>
<Text style={[textStyles]}>
<Trans>
Set your birthdate below and we'll get you back to posting and
exploring in no time!
</Trans>
</Text>
<Button
color="primary"
size="large"
label={_(msg`Click here to update your birthdate`)}
onPress={() => birthdateControl.open()}>
<ButtonText>
<Trans>Add your birthdate</Trans>
</ButtonText>
</Button>
{isUsingAppPassword && (
<Admonition type="info">
<Trans> <Trans>
Hmm, it looks like you're logged in with an{' '} In order to provide an age-appropriate experience, we need
<Span style={[a.italic]}>App Password</Span>. To set your to know your birthdate. This is a one-time thing, and your
birthdate, you'll need to log in with your main account data will be kept private.
password, or ask whomever controls this account to do so.
</Trans> </Trans>
</Admonition> </Text>
)} <Text style={[textStyles]}>
</View> <Trans>
)} Set your birthdate below and we'll get you back to posting
and exploring in no time!
</Trans>
</Text>
<Button
color="primary"
size="large"
label={_(msg`Click here to update your birthdate`)}
onPress={() => birthdateControl.open()}>
<ButtonText>
<Trans>Add your birthdate</Trans>
</ButtonText>
</Button>
<View style={[a.pt_lg, a.gap_xl]}> {isUsingAppPassword && (
<Logo width={120} textFill={t.atoms.text.color} /> <Admonition type="info">
<Text style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]}> <Trans>
<Trans> Hmm, it looks like you're logged in with an{' '}
To log out,{' '} <Span style={[a.italic]}>App Password</Span>. To set your
<SimpleInlineLinkText birthdate, you'll need to log in with your main account
label={_(msg`Click here to log out`)} password, or ask whomever controls this account to do so.
{...createStaticClick(() => { </Trans>
onPressLogout() </Admonition>
})}> )}
click here </View>
</SimpleInlineLinkText> )}
.
</Trans> <View style={[a.pt_lg, a.gap_xl]}>
</Text> <Logo width={120} textFill={t.atoms.text.color} />
<Text style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]}>
<Trans>
To log out,{' '}
<SimpleInlineLinkText
label={_(msg`Click here to log out`)}
{...createStaticClick(() => {
onPressLogout()
})}>
click here
</SimpleInlineLinkText>
.
</Trans>
</Text>
</View>
</View> </View>
</View> </ScrollView>
</ScrollView> </View>
<BirthDateSettingsDialog control={birthdateControl} /> <BirthDateSettingsDialog control={birthdateControl} />
-9
View File
@@ -3,7 +3,6 @@ import {View} from 'react-native'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher' import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
@@ -15,7 +14,6 @@ import {
useSession, useSession,
useSessionApi, useSessionApi,
} from '#/state/session' } from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {Logo} from '#/view/icons/Logo' import {Logo} from '#/view/icons/Logo'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
@@ -37,19 +35,12 @@ export function Deactivated() {
const {onPressSwitchAccount, pendingDid} = useAccountSwitcher() const {onPressSwitchAccount, pendingDid} = useAccountSwitcher()
const {setShowLoggedOut} = useLoggedOutViewControls() const {setShowLoggedOut} = useLoggedOutViewControls()
const hasOtherAccounts = accounts.length > 1 const hasOtherAccounts = accounts.length > 1
const setMinimalShellMode = useSetMinimalShellMode()
const {logoutCurrentAccount} = useSessionApi() const {logoutCurrentAccount} = useSessionApi()
const agent = useAgent() const agent = useAgent()
const [pending, setPending] = React.useState(false) const [pending, setPending] = React.useState(false)
const [error, setError] = React.useState<string | undefined>() const [error, setError] = React.useState<string | undefined>()
const queryClient = useQueryClient() const queryClient = useQueryClient()
useFocusEffect(
React.useCallback(() => {
setMinimalShellMode(true)
}, [setMinimalShellMode]),
)
const onSelectAccount = React.useCallback( const onSelectAccount = React.useCallback(
(account: SessionAccount) => { (account: SessionAccount) => {
if (account.did !== currentAccount?.did) { if (account.did !== currentAccount?.did) {
+9 -16
View File
@@ -1,6 +1,5 @@
import {useMemo, useState} from 'react' import {useMemo, useState} from 'react'
import {Modal, View} from 'react-native' import {View} from 'react-native'
import {SystemBars} from 'react-native-edge-to-edge'
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller' import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {type ComAtprotoAdminDefs, ToolsOzoneReportDefs} from '@atproto/api' import {type ComAtprotoAdminDefs, ToolsOzoneReportDefs} from '@atproto/api'
@@ -15,14 +14,14 @@ import {
} from '#/lib/constants' } from '#/lib/constants'
import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController' import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {isIOS, isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {useAgent, useSession, useSessionApi} from '#/state/session' import {useAgent, useSession, useSessionApi} from '#/state/session'
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress' import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
import {Logo} from '#/view/icons/Logo' import {Logo} from '#/view/icons/Logo'
import {atoms as a, native, useBreakpoints, useTheme, web} from '#/alf' import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as TextField from '#/components/forms/TextField' import * as TextField from '#/components/forms/TextField'
import {InlineLinkText} from '#/components/Link' import {SimpleInlineLinkText} from '#/components/Link'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import {P, Text} from '#/components/Typography' import {P, Text} from '#/components/Typography'
@@ -130,12 +129,7 @@ export function Takendown() {
useEnableKeyboardController(true) useEnableKeyboardController(true)
return ( return (
<Modal <View style={[a.util_screen_outer, a.flex_1]}>
visible
animationType={native('slide')}
presentationStyle="formSheet"
style={[web(a.util_screen_outer)]}>
{isIOS && <SystemBars style={{statusBar: 'light'}} />}
<KeyboardAwareScrollView style={[a.flex_1, t.atoms.bg]} centerContent> <KeyboardAwareScrollView style={[a.flex_1, t.atoms.bg]} centerContent>
<View <View
style={[ style={[
@@ -222,13 +216,12 @@ export function Takendown() {
<P style={[t.atoms.text_contrast_medium]}> <P style={[t.atoms.text_contrast_medium]}>
<Trans> <Trans>
Your account was found to be in violation of the{' '} Your account was found to be in violation of the{' '}
<InlineLinkText <SimpleInlineLinkText
label={_(msg`Bluesky Social Terms of Service`)} label={_(msg`Bluesky Social Terms of Service`)}
to="https://bsky.social/about/support/tos" to="https://bsky.social/about/support/tos"
style={[a.text_md, a.leading_normal]} style={[a.text_md, a.leading_normal]}>
overridePresentation>
Bluesky Social Terms of Service Bluesky Social Terms of Service
</InlineLinkText> </SimpleInlineLinkText>
. You have been sent an email outlining the specific violation . You have been sent an email outlining the specific violation
and suspension period, if applicable. You can appeal this and suspension period, if applicable. You can appeal this
decision if you believe it was made in error. decision if you believe it was made in error.
@@ -267,6 +260,6 @@ export function Takendown() {
</View> </View>
</View> </View>
)} )}
</Modal> </View>
) )
} }
@@ -35,10 +35,8 @@ import {
useLoggedOutViewControls, useLoggedOutViewControls,
} from '#/state/shell/logged-out' } from '#/state/shell/logged-out'
import {LoggedOut} from '#/view/com/auth/LoggedOut' import {LoggedOut} from '#/view/com/auth/LoggedOut'
import {Deactivated} from '#/screens/Deactivated'
import {Onboarding} from '#/screens/Onboarding' import {Onboarding} from '#/screens/Onboarding'
import {SignupQueued} from '#/screens/SignupQueued' import {SignupQueued} from '#/screens/SignupQueued'
import {Takendown} from '#/screens/Takendown'
import {atoms as a, useLayoutBreakpoints} from '#/alf' import {atoms as a, useLayoutBreakpoints} from '#/alf'
import {PolicyUpdateOverlay} from '#/components/PolicyUpdateOverlay' import {PolicyUpdateOverlay} from '#/components/PolicyUpdateOverlay'
import {BottomBarWeb} from './bottom-bar/BottomBarWeb' import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
@@ -119,15 +117,9 @@ function NativeStackNavigator({
if (hasSession && currentAccount?.signupQueued) { if (hasSession && currentAccount?.signupQueued) {
return <SignupQueued /> return <SignupQueued />
} }
if (hasSession && currentAccount?.status === 'takendown') {
return <Takendown />
}
if (showLoggedOut) { if (showLoggedOut) {
return <LoggedOut onDismiss={() => setShowLoggedOut(false)} /> return <LoggedOut onDismiss={() => setShowLoggedOut(false)} />
} }
if (currentAccount?.status === 'deactivated') {
return <Deactivated />
}
if (onboardingState.isActive) { if (onboardingState.isActive) {
return <Onboarding /> return <Onboarding />
} }
+18 -7
View File
@@ -23,6 +23,8 @@ import {useCloseAnyActiveElement} from '#/state/util'
import {Lightbox} from '#/view/com/lightbox/Lightbox' import {Lightbox} from '#/view/com/lightbox/Lightbox'
import {ModalsContainer} from '#/view/com/modals/Modal' import {ModalsContainer} from '#/view/com/modals/Modal'
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
import {Deactivated} from '#/screens/Deactivated'
import {Takendown} from '#/screens/Takendown'
import {atoms as a, select, useTheme} from '#/alf' import {atoms as a, select, useTheme} from '#/alf'
import {setSystemUITheme} from '#/alf/util/systemUI' import {setSystemUITheme} from '#/alf/util/systemUI'
import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog' import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
@@ -195,6 +197,7 @@ function DrawerLayout({children}: {children: React.ReactNode}) {
export function Shell() { export function Shell() {
const t = useTheme() const t = useTheme()
const aa = useAgeAssurance() const aa = useAgeAssurance()
const {currentAccount} = useSession()
const fullyExpandedCount = useDialogFullyExpandedCountContext() const fullyExpandedCount = useDialogFullyExpandedCountContext()
useIntentHandler() useIntentHandler()
@@ -214,15 +217,23 @@ export function Shell() {
navigationBar: t.name !== 'light' ? 'light' : 'dark', navigationBar: t.name !== 'light' ? 'light' : 'dark',
}} }}
/> />
{aa.state.access === aa.Access.None ? ( {currentAccount?.status === 'takendown' ? (
<NoAccessScreen /> <Takendown />
) : currentAccount?.status === 'deactivated' ? (
<Deactivated />
) : ( ) : (
<RoutesContainer> <>
<ShellInner /> {aa.state.access === aa.Access.None ? (
</RoutesContainer> <NoAccessScreen />
)} ) : (
<RoutesContainer>
<ShellInner />
</RoutesContainer>
)}
<RedirectOverlay /> <RedirectOverlay />
</>
)}
</View> </View>
) )
} }
+19 -7
View File
@@ -8,12 +8,15 @@ import {RemoveScrollBar} from 'react-remove-scroll-bar'
import {useIntentHandler} from '#/lib/hooks/useIntentHandler' import {useIntentHandler} from '#/lib/hooks/useIntentHandler'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {type NavigationProp} from '#/lib/routes/types' import {type NavigationProp} from '#/lib/routes/types'
import {useSession} from '#/state/session'
import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut' import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut'
import {useCloseAllActiveElements} from '#/state/util' import {useCloseAllActiveElements} from '#/state/util'
import {Lightbox} from '#/view/com/lightbox/Lightbox' import {Lightbox} from '#/view/com/lightbox/Lightbox'
import {ModalsContainer} from '#/view/com/modals/Modal' import {ModalsContainer} from '#/view/com/modals/Modal'
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
import {Deactivated} from '#/screens/Deactivated'
import {Takendown} from '#/screens/Takendown'
import {atoms as a, select, useTheme} from '#/alf' import {atoms as a, select, useTheme} from '#/alf'
import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog' import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
import {EmailDialog} from '#/components/dialogs/EmailDialog' import {EmailDialog} from '#/components/dialogs/EmailDialog'
@@ -141,17 +144,26 @@ function ShellInner() {
export function Shell() { export function Shell() {
const t = useTheme() const t = useTheme()
const aa = useAgeAssurance() const aa = useAgeAssurance()
const {currentAccount} = useSession()
return ( return (
<View style={[a.util_screen_outer, t.atoms.bg]}> <View style={[a.util_screen_outer, t.atoms.bg]}>
{aa.state.access === aa.Access.None ? ( {currentAccount?.status === 'takendown' ? (
<NoAccessScreen /> <Takendown />
) : currentAccount?.status === 'deactivated' ? (
<Deactivated />
) : ( ) : (
<RoutesContainer> <>
<ShellInner /> {aa.state.access === aa.Access.None ? (
</RoutesContainer> <NoAccessScreen />
)} ) : (
<RoutesContainer>
<ShellInner />
</RoutesContainer>
)}
<RedirectOverlay /> <RedirectOverlay />
</>
)}
</View> </View>
) )
} }