From 3ece21cb45e8b74795f4eac33a1551b303196946 Mon Sep 17 00:00:00 2001
From: Eric Bailey <git@esb.lol>
Date: Tue, 4 Jun 2024 20:02:22 -0500
Subject: [🙅] Integrate deactivate (#4308)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 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
---
 .../components/DeactivateAccountDialog.tsx         | 84 ++++++++++++++++++++--
 1 file changed, 77 insertions(+), 7 deletions(-)

(limited to 'src/screens/Settings/components/DeactivateAccountDialog.tsx')

diff --git a/src/screens/Settings/components/DeactivateAccountDialog.tsx b/src/screens/Settings/components/DeactivateAccountDialog.tsx
index 4330ffcaa..99999d068 100644
--- a/src/screens/Settings/components/DeactivateAccountDialog.tsx
+++ b/src/screens/Settings/components/DeactivateAccountDialog.tsx
@@ -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>
+      )}
+    </>
   )
 }
-- 
cgit 1.4.1

