Handle token step
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
import {useMutation} from '@tanstack/react-query'
|
||||||
|
|
||||||
|
import {useAgent, useSession} from '#/state/session'
|
||||||
|
|
||||||
|
export function useConfirmEmail() {
|
||||||
|
const agent = useAgent()
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({token}: {token: string}) => {
|
||||||
|
if (!currentAccount?.email) {
|
||||||
|
throw new Error('No email found for the current account')
|
||||||
|
}
|
||||||
|
|
||||||
|
await agent.com.atproto.server.confirmEmail({
|
||||||
|
email: currentAccount.email,
|
||||||
|
token: token.trim(),
|
||||||
|
})
|
||||||
|
await agent.resumeSession(agent.session!)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ import {atoms as a, useTheme} from '#/alf'
|
|||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {ResendEmailText} from '#/components/dialogs/EmailDialog/components/ResendEmailText'
|
import {ResendEmailText} from '#/components/dialogs/EmailDialog/components/ResendEmailText'
|
||||||
|
import {TokenField} from '#/components/dialogs/EmailDialog/components/TokenField'
|
||||||
|
import {useConfirmEmail} from '#/components/dialogs/EmailDialog/data/useConfirmEmail'
|
||||||
import {useRequestEmailVerification} from '#/components/dialogs/EmailDialog/data/useRequestEmailVerification'
|
import {useRequestEmailVerification} from '#/components/dialogs/EmailDialog/data/useRequestEmailVerification'
|
||||||
import {type Screen} from '#/components/dialogs/EmailDialog/types'
|
import {type Screen} from '#/components/dialogs/EmailDialog/types'
|
||||||
import {Divider} from '#/components/Divider'
|
import {Divider} from '#/components/Divider'
|
||||||
@@ -25,17 +27,25 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
|
|
||||||
const [sentEmail, setSentEmail] = useState(false)
|
const [step, setStep] = useState<
|
||||||
|
'default' | 'sent' | 'token' | 'tokenConfirmed'
|
||||||
|
>('default')
|
||||||
const [sendingStatus, setSendingStatus] = useState<'sending' | null>(null)
|
const [sendingStatus, setSendingStatus] = useState<'sending' | null>(null)
|
||||||
const {mutateAsync: requestEmailVerification} = useRequestEmailVerification()
|
const {mutateAsync: requestEmailVerification} = useRequestEmailVerification()
|
||||||
|
|
||||||
|
const [token, setToken] = useState('')
|
||||||
|
const [confirmingStatus, setConfirmingStatus] = useState<'sending' | null>(
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
const {mutateAsync: confirmEmail} = useConfirmEmail()
|
||||||
|
|
||||||
const handleRequestEmailVerification = async () => {
|
const handleRequestEmailVerification = async () => {
|
||||||
setError('')
|
setError('')
|
||||||
setSendingStatus('sending')
|
setSendingStatus('sending')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await wait(1000, requestEmailVerification())
|
await wait(1000, requestEmailVerification())
|
||||||
setSentEmail(true)
|
setStep('sent')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('EmailDialog: sending verification email failed', {
|
logger.error('EmailDialog: sending verification email failed', {
|
||||||
safeMessage: e,
|
safeMessage: e,
|
||||||
@@ -46,24 +56,48 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleConfirmEmail = async () => {
|
||||||
|
setError('')
|
||||||
|
setConfirmingStatus('sending')
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wait(1000, confirmEmail({token}))
|
||||||
|
setStep('tokenConfirmed')
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('EmailDialog: confirming email failed', {
|
||||||
|
safeMessage: e,
|
||||||
|
})
|
||||||
|
setError(_(msg`Failed to verify email, please try again.`))
|
||||||
|
} finally {
|
||||||
|
setConfirmingStatus(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
<View style={[a.gap_sm]}>
|
<View style={[a.gap_sm]}>
|
||||||
<Text style={[a.text_xl, a.font_heavy]}>
|
<Text style={[a.text_xl, a.font_heavy]}>
|
||||||
{sentEmail ? (
|
{step === 'sent' ? (
|
||||||
<>
|
<>
|
||||||
<Span style={{top: 1}}>
|
<Span style={{top: 1}}>
|
||||||
<Check size="sm" fill={t.palette.positive_500} />
|
<Check size="sm" fill={t.palette.positive_500} />
|
||||||
</Span>{' '}
|
</Span>{' '}
|
||||||
<Trans>Email sent!</Trans>
|
<Trans>Email sent!</Trans>
|
||||||
</>
|
</>
|
||||||
|
) : step === 'tokenConfirmed' ? (
|
||||||
|
<>
|
||||||
|
<Span style={{top: 1}}>
|
||||||
|
<Check size="sm" fill={t.palette.positive_500} />
|
||||||
|
</Span>{' '}
|
||||||
|
<Trans>Email verification complete</Trans>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Trans>Verify email</Trans>
|
<Trans>Verify email</Trans>
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||||
{sentEmail ? (
|
{step === 'sent' ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
We sent an email to{' '}
|
We sent an email to{' '}
|
||||||
<Span style={[a.font_bold, t.atoms.text]}>
|
<Span style={[a.font_bold, t.atoms.text]}>
|
||||||
@@ -72,6 +106,19 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
containing a link. Click on it to complete the email verification
|
containing a link. Click on it to complete the email verification
|
||||||
process.
|
process.
|
||||||
</Trans>
|
</Trans>
|
||||||
|
) : step === 'token' ? (
|
||||||
|
<Trans>
|
||||||
|
Enter the code we sent to{' '}
|
||||||
|
<Span style={[a.font_bold, t.atoms.text]}>
|
||||||
|
{currentAccount!.email}
|
||||||
|
</Span>{' '}
|
||||||
|
below.
|
||||||
|
</Trans>
|
||||||
|
) : step === 'tokenConfirmed' ? (
|
||||||
|
<Trans>
|
||||||
|
You have successfully verified your email address. You can close
|
||||||
|
this dialog.
|
||||||
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans>
|
<Trans>
|
||||||
We'll send you an email to{' '}
|
We'll send you an email to{' '}
|
||||||
@@ -84,10 +131,12 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{sentEmail && <ResendEmailText onPress={requestEmailVerification} />}
|
{step === 'sent' && (
|
||||||
|
<ResendEmailText onPress={requestEmailVerification} />
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!sentEmail && (
|
{step === 'default' ? (
|
||||||
<>
|
<>
|
||||||
{error && <Admonition type="error"> {error} </Admonition>}
|
{error && <Admonition type="error"> {error} </Admonition>}
|
||||||
|
|
||||||
@@ -95,7 +144,7 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
label={_(msg`Send verification email`)}
|
label={_(msg`Send verification email`)}
|
||||||
size="large"
|
size="large"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color={'primary'}
|
color="primary"
|
||||||
onPress={handleRequestEmailVerification}
|
onPress={handleRequestEmailVerification}
|
||||||
disabled={sendingStatus === 'sending'}>
|
disabled={sendingStatus === 'sending'}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
@@ -114,13 +163,38 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
Have a code?{' '}
|
Have a code?{' '}
|
||||||
<InlineLinkText
|
<InlineLinkText
|
||||||
label={_(msg`Enter code`)}
|
label={_(msg`Enter code`)}
|
||||||
{...createStaticClick(() => {})}>
|
{...createStaticClick(() => {
|
||||||
|
setStep('token')
|
||||||
|
})}>
|
||||||
Click here.
|
Click here.
|
||||||
</InlineLinkText>
|
</InlineLinkText>
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</>
|
</>
|
||||||
)}
|
) : step === 'token' ? (
|
||||||
|
<>
|
||||||
|
<TokenField
|
||||||
|
value={token}
|
||||||
|
onChangeText={setToken}
|
||||||
|
onSubmitEditing={() => {}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{error && <Admonition type="error"> {error} </Admonition>}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={_(msg`Verify`)}
|
||||||
|
size="large"
|
||||||
|
variant="solid"
|
||||||
|
color="primary"
|
||||||
|
onPress={handleConfirmEmail}
|
||||||
|
disabled={!token || confirmingStatus === 'sending'}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Verify code</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
{confirmingStatus === 'sending' && <ButtonIcon icon={Loader} />}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user