Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be47ead410 | |||
| 6964b9ab76 | |||
| abd28fa4c2 | |||
| 857ee41723 | |||
| 261b60eff4 | |||
| 80a20993bd |
@@ -13,7 +13,7 @@ export type LogEvents = {
|
||||
withPassword: boolean
|
||||
}
|
||||
'account:loggedOut': {
|
||||
logContext: 'SwitchAccount' | 'Settings' | 'SignupQueued'
|
||||
logContext: 'SwitchAccount' | 'Settings' | 'SignupQueued' | 'Deactivated'
|
||||
}
|
||||
'notifications:openApp': {}
|
||||
'notifications:request': {
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
|
||||
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {type SessionAccount, useSession, useSessionApi} from '#/state/session'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {ScrollView} from '#/view/com/util/Views'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {AccountList} from '#/components/AccountList'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
const COL_WIDTH = 400
|
||||
|
||||
export function Deactivated() {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const insets = useSafeAreaInsets()
|
||||
const {currentAccount, accounts} = useSession()
|
||||
const {onPressSwitchAccount, pendingDid} = useAccountSwitcher()
|
||||
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||
const hasOtherAccounts = accounts.length > 1
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const {logout} = useSessionApi()
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
setMinimalShellMode(true)
|
||||
}, [setMinimalShellMode]),
|
||||
)
|
||||
|
||||
const onSelectAccount = React.useCallback(
|
||||
(account: SessionAccount) => {
|
||||
if (account.did !== currentAccount?.did) {
|
||||
onPressSwitchAccount(account, 'SwitchAccount')
|
||||
}
|
||||
},
|
||||
[currentAccount, onPressSwitchAccount],
|
||||
)
|
||||
|
||||
const onPressAddAccount = React.useCallback(() => {
|
||||
setShowLoggedOut(true)
|
||||
}, [setShowLoggedOut])
|
||||
|
||||
const onPressLogout = React.useCallback(() => {
|
||||
if (isWeb) {
|
||||
// We're switching accounts, which remounts the entire app.
|
||||
// On mobile, this gets us Home, but on the web we also need reset the URL.
|
||||
// We can't change the URL via a navigate() call because the navigator
|
||||
// itself is about to unmount, and it calls pushState() too late.
|
||||
// So we change the URL ourselves. The navigator will pick it up on remount.
|
||||
history.pushState(null, '', '/')
|
||||
}
|
||||
logout('Deactivated')
|
||||
}, [logout])
|
||||
|
||||
return (
|
||||
<View style={[a.h_full_vh, a.flex_1, t.atoms.bg]}>
|
||||
<ScrollView
|
||||
style={[a.h_full, a.w_full]}
|
||||
contentContainerStyle={{borderWidth: 0}}>
|
||||
<View
|
||||
style={[
|
||||
a.px_2xl,
|
||||
{
|
||||
paddingTop: isWeb ? 64 : insets.top,
|
||||
paddingBottom: isWeb ? 64 : insets.bottom,
|
||||
},
|
||||
]}>
|
||||
<View style={[a.flex_row, a.justify_center]}>
|
||||
<View style={[a.w_full, {maxWidth: COL_WIDTH}]}>
|
||||
<View
|
||||
style={[a.w_full, a.justify_center, a.align_center, a.pb_5xl]}>
|
||||
<Logo width={40} />
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs, a.pb_3xl]}>
|
||||
<Text style={[a.text_xl, a.font_bold, a.leading_snug]}>
|
||||
<Trans>Welcome back!</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_sm, a.leading_snug]}>
|
||||
<Trans>
|
||||
You previously deactivated @{currentAccount?.handle}.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_sm, a.leading_snug, a.pb_md]}>
|
||||
<Trans>
|
||||
You can reactivate your account to continue logging in. Your
|
||||
profile and posts will be visible to other users.
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<View style={[a.gap_sm]}>
|
||||
<Button
|
||||
label={_(msg`Reactivate your account`)}
|
||||
size="medium"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
onPress={() => setShowLoggedOut(true)}>
|
||||
<ButtonText>
|
||||
<Trans>Yes, reactivate my account</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
label={_(msg`Cancel reactivation and log out`)}
|
||||
size="medium"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
onPress={onPressLogout}>
|
||||
<ButtonText>
|
||||
<Trans>Cancel</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={[a.pb_3xl]}>
|
||||
<Divider />
|
||||
</View>
|
||||
|
||||
{hasOtherAccounts ? (
|
||||
<>
|
||||
<Text
|
||||
style={[
|
||||
t.atoms.text_contrast_medium,
|
||||
a.pb_md,
|
||||
a.leading_snug,
|
||||
]}>
|
||||
<Trans>Or, log into one of your other accounts.</Trans>
|
||||
</Text>
|
||||
<AccountList
|
||||
onSelectAccount={onSelectAccount}
|
||||
onSelectOther={onPressAddAccount}
|
||||
otherLabel={_(msg`Add account`)}
|
||||
pendingDid={pendingDid}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text
|
||||
style={[
|
||||
t.atoms.text_contrast_medium,
|
||||
a.pb_md,
|
||||
a.leading_snug,
|
||||
]}>
|
||||
<Trans>Or, continue with another account.</Trans>
|
||||
</Text>
|
||||
<Button
|
||||
label={_(msg`Log in or sign up`)}
|
||||
size="medium"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
onPress={() => setShowLoggedOut(true)}>
|
||||
<ButtonText>
|
||||
<Trans>Log in or sign up</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {DialogOuterProps} from '#/components/Dialog'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function DeactivateAccountDialog({
|
||||
control,
|
||||
}: {
|
||||
control: DialogOuterProps['control']
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
|
||||
return (
|
||||
<Prompt.Outer control={control} testID="confirmModal">
|
||||
<Prompt.TitleText>{_(msg`Deactivate account`)}</Prompt.TitleText>
|
||||
<Prompt.DescriptionText>
|
||||
<Trans>
|
||||
Your profile, posts, feeds, and lists will no longer be visible to
|
||||
other Bluesky users. You can reactivate your account at any time by
|
||||
logging in.
|
||||
</Trans>
|
||||
</Prompt.DescriptionText>
|
||||
|
||||
<View style={[a.pb_xl]}>
|
||||
<Divider />
|
||||
<View style={[a.gap_sm, a.pt_lg, a.pb_xl]}>
|
||||
<Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
|
||||
<Trans>
|
||||
There is no time limit for account deactivation, come back any
|
||||
time.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
|
||||
<Trans>
|
||||
If you're trying to change your handle or email, do so before you
|
||||
deactivate.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Divider />
|
||||
</View>
|
||||
<Prompt.Actions>
|
||||
<Prompt.Action
|
||||
cta={_(msg`Yes, deactivate`)}
|
||||
onPress={() => {}}
|
||||
color="negative"
|
||||
/>
|
||||
<Prompt.Cancel />
|
||||
</Prompt.Actions>
|
||||
</Prompt.Outer>
|
||||
)
|
||||
}
|
||||
@@ -18,6 +18,9 @@ const accountSchema = z.object({
|
||||
refreshJwt: z.string().optional(), // optional because it can expire
|
||||
accessJwt: z.string().optional(), // optional because it can expire
|
||||
signupQueued: z.boolean().optional(),
|
||||
status: z
|
||||
.enum(['active', 'takendown', 'suspended', 'deactivated'])
|
||||
.optional(),
|
||||
pdsUrl: z.string().optional(),
|
||||
})
|
||||
export type PersistedAccount = z.infer<typeof accountSchema>
|
||||
|
||||
@@ -59,6 +59,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-1",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -96,6 +97,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -145,6 +147,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-1",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -192,6 +195,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-1",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "alice-access-jwt-1",
|
||||
@@ -204,6 +208,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-1",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -251,6 +256,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "bob-access-jwt-1",
|
||||
@@ -263,6 +269,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-1",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -308,6 +315,7 @@ describe('session', () => {
|
||||
"refreshJwt": "jay-refresh-jwt-1",
|
||||
"service": "https://jay.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "alice-access-jwt-2",
|
||||
@@ -320,6 +328,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "bob-access-jwt-1",
|
||||
@@ -332,6 +341,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-1",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -373,6 +383,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://jay.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": undefined,
|
||||
@@ -385,6 +396,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": undefined,
|
||||
@@ -397,6 +409,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -455,6 +468,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -499,6 +513,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -610,6 +625,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-1",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -690,6 +706,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -740,6 +757,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-3",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -790,6 +808,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-4",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -946,6 +965,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-1",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "alice-access-jwt-2",
|
||||
@@ -958,6 +978,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1006,6 +1027,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-2",
|
||||
"service": "https://bob.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "alice-access-jwt-2",
|
||||
@@ -1018,6 +1040,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1165,6 +1188,7 @@ describe('session', () => {
|
||||
"refreshJwt": "alice-refresh-jwt-1",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1227,6 +1251,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1289,6 +1314,7 @@ describe('session', () => {
|
||||
"refreshJwt": undefined,
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1380,6 +1406,7 @@ describe('session', () => {
|
||||
"refreshJwt": "jay-refresh-jwt-1",
|
||||
"service": "https://jay.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
{
|
||||
"accessJwt": "bob-access-jwt-2",
|
||||
@@ -1392,6 +1419,7 @@ describe('session', () => {
|
||||
"refreshJwt": "bob-refresh-jwt-2",
|
||||
"service": "https://alice.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
@@ -1438,6 +1466,7 @@ describe('session', () => {
|
||||
"refreshJwt": "clarence-refresh-jwt-2",
|
||||
"service": "https://clarence.com/",
|
||||
"signupQueued": false,
|
||||
"status": "active",
|
||||
},
|
||||
],
|
||||
"currentAgentState": {
|
||||
|
||||
@@ -235,6 +235,8 @@ export function agentToSessionAccount(
|
||||
refreshJwt: agent.session.refreshJwt,
|
||||
accessJwt: agent.session.accessJwt,
|
||||
signupQueued: isSignupQueued(agent.session.accessJwt),
|
||||
// @ts-expect-error TODO remove when backend is ready
|
||||
status: agent.session.status || 'active',
|
||||
pdsUrl: agent.pdsUrl?.toString(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {colors, gradients, s} from 'lib/styles'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {isAndroid} from 'platform/detection'
|
||||
import {isAndroid, isWeb} from 'platform/detection'
|
||||
import {DeactivateAccountDialog} from '#/screens/Settings/components/DeactivateAccountDialog'
|
||||
import {atoms as a, useTheme as useNewTheme} from '#/alf'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {Text as NewText} from '#/components/Typography'
|
||||
import {resetToTab} from '../../../Navigation'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {Text} from '../util/text/Text'
|
||||
@@ -30,6 +36,7 @@ export const snapPoints = isAndroid ? ['90%'] : ['55%']
|
||||
export function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const t = useNewTheme()
|
||||
const {currentAccount} = useSession()
|
||||
const agent = useAgent()
|
||||
const {removeAccount} = useSessionApi()
|
||||
@@ -41,6 +48,7 @@ export function Component({}: {}) {
|
||||
const [password, setPassword] = React.useState<string>('')
|
||||
const [isProcessing, setIsProcessing] = React.useState<boolean>(false)
|
||||
const [error, setError] = React.useState<string>('')
|
||||
const deactivateAccountControl = useDialogControl()
|
||||
const onPressSendEmail = async () => {
|
||||
setError('')
|
||||
setIsProcessing(true)
|
||||
@@ -168,6 +176,47 @@ export function Component({}: {}) {
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
|
||||
<View style={[!isWeb && a.px_xl]}>
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.flex_row,
|
||||
a.gap_sm,
|
||||
a.mt_lg,
|
||||
a.p_lg,
|
||||
a.rounded_sm,
|
||||
t.atoms.bg_contrast_25,
|
||||
]}>
|
||||
<CircleInfo
|
||||
size="md"
|
||||
style={[
|
||||
a.relative,
|
||||
{
|
||||
top: -1,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<NewText style={[a.leading_snug, a.flex_1]}>
|
||||
<Trans>
|
||||
You can also temporarily deactivate your account instead,
|
||||
and reactivate it at any time.
|
||||
</Trans>{' '}
|
||||
<InlineLinkText
|
||||
to="#"
|
||||
onPress={e => {
|
||||
e.preventDefault()
|
||||
deactivateAccountControl.open()
|
||||
return false
|
||||
}}>
|
||||
<Trans>Click here for more information.</Trans>
|
||||
</InlineLinkText>
|
||||
</NewText>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<DeactivateAccountDialog control={deactivateAccountControl} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -60,6 +60,7 @@ import {Text} from 'view/com/util/text/Text'
|
||||
import * as Toast from 'view/com/util/Toast'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {ScrollView} from 'view/com/util/Views'
|
||||
import {DeactivateAccountDialog} from '#/screens/Settings/components/DeactivateAccountDialog'
|
||||
import {useTheme} from '#/alf'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
|
||||
@@ -306,6 +307,11 @@ export function SettingsScreen({}: Props) {
|
||||
Toast.show(_(msg`Legacy storage cleared, you need to restart the app now.`))
|
||||
}, [_])
|
||||
|
||||
const deactivateAccountControl = useDialogControl()
|
||||
const onPressDeactivateAccount = React.useCallback(() => {
|
||||
deactivateAccountControl.open()
|
||||
}, [deactivateAccountControl])
|
||||
|
||||
const {mutate: onPressDeleteChatDeclaration} = useDeleteActorDeclaration()
|
||||
|
||||
return (
|
||||
@@ -790,6 +796,29 @@ export function SettingsScreen({}: Props) {
|
||||
<Trans>Export My Data</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCard]}
|
||||
onPress={onPressDeactivateAccount}
|
||||
accessible={true}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Deactivate account`)}
|
||||
accessibilityHint={_(
|
||||
msg`Opens modal for account deactivation confirmation`,
|
||||
)}>
|
||||
<View style={[styles.iconContainer, dangerBg]}>
|
||||
<FontAwesomeIcon
|
||||
icon={'users-slash'}
|
||||
style={dangerText as FontAwesomeIconStyle}
|
||||
size={18}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={dangerText}>
|
||||
<Trans>Deactivate my account</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<DeactivateAccountDialog control={deactivateAccountControl} />
|
||||
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCard]}
|
||||
onPress={onPressDeleteAccount}
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
useLoggedOutViewControls,
|
||||
} from '#/state/shell/logged-out'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {Deactivated} from '#/screens/Deactivated'
|
||||
import {Onboarding} from '#/screens/Onboarding'
|
||||
import {SignupQueued} from '#/screens/SignupQueued'
|
||||
import {LoggedOut} from '../com/auth/LoggedOut'
|
||||
@@ -108,6 +109,9 @@ function NativeStackNavigator({
|
||||
if (showLoggedOut) {
|
||||
return <LoggedOut onDismiss={() => setShowLoggedOut(false)} />
|
||||
}
|
||||
if (currentAccount?.status === 'deactivated') {
|
||||
return <Deactivated />
|
||||
}
|
||||
if (onboardingState.isActive) {
|
||||
return <Onboarding />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user