forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React from 'react'
2import {View} from 'react-native'
3import {useSafeAreaInsets} from 'react-native-safe-area-context'
4import {msg, Trans} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6import {useQueryClient} from '@tanstack/react-query'
7
8import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
9import {logger} from '#/logger'
10import {
11 type SessionAccount,
12 useAgent,
13 useSession,
14 useSessionApi,
15} from '#/state/session'
16import {useLoggedOutViewControls} from '#/state/shell/logged-out'
17import {Logo} from '#/view/icons/Logo'
18import {atoms as a, useTheme} from '#/alf'
19import {AccountList} from '#/components/AccountList'
20import {Button, ButtonIcon, ButtonText} from '#/components/Button'
21import {Divider} from '#/components/Divider'
22import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
23import * as Layout from '#/components/Layout'
24import {Loader} from '#/components/Loader'
25import {Text} from '#/components/Typography'
26import {IS_WEB} from '#/env'
27
28const COL_WIDTH = 400
29
30export function Deactivated() {
31 const {_} = useLingui()
32 const t = useTheme()
33 const insets = useSafeAreaInsets()
34 const {currentAccount, accounts} = useSession()
35 const {onPressSwitchAccount, pendingDid} = useAccountSwitcher()
36 const {setShowLoggedOut} = useLoggedOutViewControls()
37 const hasOtherAccounts = accounts.length > 1
38 const {logoutCurrentAccount} = useSessionApi()
39 const agent = useAgent()
40 const [pending, setPending] = React.useState(false)
41 const [error, setError] = React.useState<string | undefined>()
42 const queryClient = useQueryClient()
43
44 const onSelectAccount = React.useCallback(
45 (account: SessionAccount) => {
46 if (account.did !== currentAccount?.did) {
47 onPressSwitchAccount(account, 'SwitchAccount')
48 }
49 },
50 [currentAccount, onPressSwitchAccount],
51 )
52
53 const onPressAddAccount = React.useCallback(() => {
54 setShowLoggedOut(true)
55 }, [setShowLoggedOut])
56
57 const onPressLogout = React.useCallback(() => {
58 if (IS_WEB) {
59 // We're switching accounts, which remounts the entire app.
60 // On mobile, this gets us Home, but on the web we also need reset the URL.
61 // We can't change the URL via a navigate() call because the navigator
62 // itself is about to unmount, and it calls pushState() too late.
63 // So we change the URL ourselves. The navigator will pick it up on remount.
64 history.pushState(null, '', '/')
65 }
66 logoutCurrentAccount('Deactivated')
67 }, [logoutCurrentAccount])
68
69 const handleActivate = React.useCallback(async () => {
70 try {
71 setPending(true)
72 await agent.com.atproto.server.activateAccount()
73 await queryClient.resetQueries()
74 await agent.resumeSession(agent.session!)
75 } catch (e: any) {
76 switch (e.message) {
77 case 'Bad token scope':
78 setError(
79 _(
80 msg`You're signed in with an App Password. Please sign in with your main password to continue deactivating your account.`,
81 ),
82 )
83 break
84 default:
85 setError(_(msg`Something went wrong, please try again`))
86 break
87 }
88
89 logger.error(e, {
90 message: 'Failed to activate account',
91 })
92 } finally {
93 setPending(false)
94 }
95 }, [_, agent, setPending, setError, queryClient])
96
97 return (
98 <View style={[a.util_screen_outer, a.flex_1]}>
99 <Layout.Content
100 ignoreTabletLayoutOffset
101 contentContainerStyle={[
102 a.px_2xl,
103 {
104 paddingTop: IS_WEB ? 64 : insets.top + 16,
105 paddingBottom: IS_WEB ? 64 : insets.bottom,
106 },
107 ]}>
108 <View
109 style={[a.w_full, {marginHorizontal: 'auto', maxWidth: COL_WIDTH}]}>
110 <View style={[a.w_full, a.justify_center, a.align_center, a.pb_5xl]}>
111 <Logo width={40} />
112 </View>
113
114 <View style={[a.gap_xs, a.pb_3xl]}>
115 <Text style={[a.text_xl, a.font_semi_bold, a.leading_snug]}>
116 <Trans>Welcome back!</Trans>
117 </Text>
118 <Text style={[a.text_sm, a.leading_snug]}>
119 <Trans>
120 You previously deactivated @{currentAccount?.handle}.
121 </Trans>
122 </Text>
123 <Text style={[a.text_sm, a.leading_snug, a.pb_md]}>
124 <Trans>
125 You can reactivate your account to continue logging in. Your
126 profile and posts will be visible to other users.
127 </Trans>
128 </Text>
129
130 <View style={[a.gap_sm]}>
131 <Button
132 label={_(msg`Reactivate your account`)}
133 size="large"
134 variant="solid"
135 color="primary"
136 onPress={handleActivate}>
137 <ButtonText>
138 <Trans>Yes, reactivate my account</Trans>
139 </ButtonText>
140 {pending && <ButtonIcon icon={Loader} position="right" />}
141 </Button>
142 <Button
143 label={_(msg`Cancel reactivation and sign out`)}
144 size="large"
145 variant="solid"
146 color="secondary"
147 onPress={onPressLogout}>
148 <ButtonText>
149 <Trans>Cancel</Trans>
150 </ButtonText>
151 </Button>
152 </View>
153
154 {error && (
155 <View
156 style={[
157 a.flex_row,
158 a.gap_sm,
159 a.mt_md,
160 a.p_md,
161 a.rounded_sm,
162 t.atoms.bg_contrast_25,
163 ]}>
164 <CircleInfo size="md" fill={t.palette.negative_400} />
165 <Text style={[a.flex_1, a.leading_snug]}>{error}</Text>
166 </View>
167 )}
168 </View>
169
170 <View style={[a.pb_3xl]}>
171 <Divider />
172 </View>
173
174 {hasOtherAccounts ? (
175 <>
176 <Text
177 style={[t.atoms.text_contrast_medium, a.pb_md, a.leading_snug]}>
178 <Trans>Or, sign in to one of your other accounts.</Trans>
179 </Text>
180 <AccountList
181 onSelectAccount={onSelectAccount}
182 onSelectOther={onPressAddAccount}
183 otherLabel={_(msg`Add account`)}
184 pendingDid={pendingDid}
185 />
186 </>
187 ) : (
188 <>
189 <Text
190 style={[t.atoms.text_contrast_medium, a.pb_md, a.leading_snug]}>
191 <Trans>Or, continue with another account.</Trans>
192 </Text>
193 <Button
194 label={_(msg`Sign in or create an account`)}
195 size="large"
196 variant="solid"
197 color="secondary"
198 onPress={() => setShowLoggedOut(true)}>
199 <ButtonText>
200 <Trans>Sign in or create an account</Trans>
201 </ButtonText>
202 </Button>
203 </>
204 )}
205 </View>
206 </Layout.Content>
207 </View>
208 )
209}