[🙅] Integrate deactivate (#4308)

* Update types

(cherry picked from commit 27deac1f367825771ba76fa098ec1b0a62dcf64a)

* Integrate into deactivate dialog

(cherry picked from commit 84f299a447259cc1fbfc7be607e28197779e4ec1)

* Integrate into Deactivated screen

(cherry picked from commit 29193f34822ecdf11e2a407197fa230285dfe846)

* Bump api sdk

(cherry picked from commit 738c622d3e5a23bfbb0d3bdce3a6bdf01e54ca60)

* Update permalink

(cherry picked from commit c10bf5c071d76c3054bc4ce9d313c10b1820f038)

* Bump sdk pkg

* Update types to match backend

* Loosen types for forwards compat

* Hydrate status from persisted data

* Refresh session when re-activating, clear query cache

* Show app password error

* Refactor dialog to clear state when closed

* Add app password error to Deactivated screen
This commit is contained in:
Eric Bailey 2024-06-04 20:02:22 -05:00 committed by GitHub
parent e64b7cf698
commit 3ece21cb45
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 216 additions and 20 deletions

View file

@ -3,9 +3,14 @@ import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {atoms as a, useTheme} from '#/alf'
import {logger} from '#/logger'
import {useAgent, useSessionApi} from '#/state/session'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {DialogOuterProps} from '#/components/Dialog'
import {Divider} from '#/components/Divider'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {Loader} from '#/components/Loader'
import * as Prompt from '#/components/Prompt'
import {Text} from '#/components/Typography'
@ -13,12 +18,58 @@ export function DeactivateAccountDialog({
control,
}: {
control: DialogOuterProps['control']
}) {
return (
<Prompt.Outer control={control}>
<DeactivateAccountDialogInner control={control} />
</Prompt.Outer>
)
}
function DeactivateAccountDialogInner({
control,
}: {
control: DialogOuterProps['control']
}) {
const t = useTheme()
const {gtMobile} = useBreakpoints()
const {_} = useLingui()
const agent = useAgent()
const {logout} = useSessionApi()
const [pending, setPending] = React.useState(false)
const [error, setError] = React.useState<string | undefined>()
const handleDeactivate = React.useCallback(async () => {
try {
setPending(true)
await agent.com.atproto.server.deactivateAccount({})
control.close(() => {
logout('Deactivated')
})
} catch (e: any) {
switch (e.message) {
case 'Bad token scope':
setError(
_(
msg`You're logged in with an App Password. Please log in with your main password to continue deactivating your account.`,
),
)
break
default:
setError(_(msg`Something went wrong, please try again`))
break
}
logger.error(e, {
context: 'Failed to deactivate account',
})
} finally {
setPending(false)
}
}, [agent, control, logout, _, setPending])
return (
<Prompt.Outer control={control} testID="confirmModal">
<>
<Prompt.TitleText>{_(msg`Deactivate account`)}</Prompt.TitleText>
<Prompt.DescriptionText>
<Trans>
@ -48,13 +99,32 @@ export function DeactivateAccountDialog({
<Divider />
</View>
<Prompt.Actions>
<Prompt.Action
cta={_(msg`Yes, deactivate`)}
onPress={() => {}}
<Button
variant="solid"
color="negative"
/>
size={gtMobile ? 'small' : 'medium'}
label={_(msg`Yes, deactivate`)}
onPress={handleDeactivate}>
<ButtonText>{_(msg`Yes, deactivate`)}</ButtonText>
{pending && <ButtonIcon icon={Loader} position="right" />}
</Button>
<Prompt.Cancel />
</Prompt.Actions>
</Prompt.Outer>
{error && (
<View
style={[
a.flex_row,
a.gap_sm,
a.mt_md,
a.p_md,
a.rounded_sm,
t.atoms.bg_contrast_25,
]}>
<CircleInfo size="md" fill={t.palette.negative_400} />
<Text style={[a.flex_1, a.leading_snug]}>{error}</Text>
</View>
)}
</>
)
}