Modernise change email flow (#8106)

* use new verify email dialog in 2fa flow

* alf change email flow

* Fallback change email dialog

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update ChangeEmailDialog.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update Email2FAToggle.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* don't use existing email as default value

* increase max width of email dialogs

* Use ALF verify email dialog for reminder (#5924)

* use new verify email dialog for reminder

* style tweaks, improve web

* add a lil toast

* Apply suggestions from code review

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Ditch close and push up image

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
Co-authored-by: Eric Bailey <git@esb.lol>

* delete old change/verify email modals (#8122)

(cherry picked from commit fceb655b3b)

* Translate email placeholder

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Align copy

* Clean up error handling

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
Samuel Newman
2025-04-23 19:22:08 +03:00
committed by GitHub
parent 118d385b10
commit 70dbc94766
11 changed files with 462 additions and 728 deletions
+11 -2
View File
@@ -9,6 +9,7 @@ import * as SettingsList from '#/screens/Settings/components/SettingsList'
import {atoms as a, useTheme} from '#/alf'
import {useDialogControl} from '#/components/Dialog'
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
import {ChangeEmailDialog} from '#/components/dialogs/ChangeEmailDialog'
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
import {At_Stroke2_Corner2_Rounded as AtIcon} from '#/components/icons/At'
import {BirthdayCake_Stroke2_Corner2_Rounded as BirthdayCakeIcon} from '#/components/icons/BirthdayCake'
@@ -31,6 +32,7 @@ export function AccountSettingsScreen({}: Props) {
const {currentAccount} = useSession()
const {openModal} = useModalControls()
const verifyEmailControl = useDialogControl()
const changeEmailControl = useDialogControl()
const birthdayControl = useDialogControl()
const changeHandleControl = useDialogControl()
const exportCarControl = useDialogControl()
@@ -95,7 +97,7 @@ export function AccountSettingsScreen({}: Props) {
)}
<SettingsList.PressableItem
label={_(msg`Change email`)}
onPress={() => openModal({name: 'change-email'})}>
onPress={() => changeEmailControl.open()}>
<SettingsList.ItemIcon icon={PencilIcon} />
<SettingsList.ItemText>
<Trans>Change email</Trans>
@@ -165,7 +167,14 @@ export function AccountSettingsScreen({}: Props) {
</SettingsList.Container>
</Layout.Content>
<VerifyEmailDialog control={verifyEmailControl} />
<ChangeEmailDialog
control={changeEmailControl}
verifyEmailControl={verifyEmailControl}
/>
<VerifyEmailDialog
control={verifyEmailControl}
changeEmailControl={changeEmailControl}
/>
<BirthDateSettingsDialog control={birthdayControl} />
<ChangeHandleDialog control={changeHandleControl} />
<ExportCarDialog control={exportCarControl} />
+20 -1
View File
@@ -3,7 +3,7 @@ import {LayoutAnimation, Pressable, View} from 'react-native'
import {Linking} from 'react-native'
import {useReducedMotion} from 'react-native-reanimated'
import {type AppBskyActorDefs, moderateProfile} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {msg, t, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
@@ -18,6 +18,7 @@ import {
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import * as persisted from '#/state/persisted'
import {clearStorage} from '#/state/persisted'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useDeleteActorDeclaration} from '#/state/queries/messages/actor-declaration'
@@ -359,6 +360,17 @@ function DevOptions() {
Toast.show(_(msg`Storage cleared, you need to restart the app now.`))
}
const onPressUnsnoozeReminder = () => {
const lastEmailConfirm = new Date()
// wind back 3 days
lastEmailConfirm.setDate(lastEmailConfirm.getDate() - 3)
persisted.write('reminders', {
...persisted.get('reminders'),
lastEmailConfirm: lastEmailConfirm.toISOString(),
})
Toast.show(t`You probably want to restart the app now.`)
}
return (
<>
<SettingsList.PressableItem
@@ -396,6 +408,13 @@ function DevOptions() {
<Trans>Reset onboarding state</Trans>
</SettingsList.ItemText>
</SettingsList.PressableItem>
<SettingsList.PressableItem
onPress={onPressUnsnoozeReminder}
label={_(msg`Unsnooze email reminder`)}>
<SettingsList.ItemText>
<Trans>Unsnooze email reminder</Trans>
</SettingsList.ItemText>
</SettingsList.PressableItem>
<SettingsList.PressableItem
onPress={() => clearAllStorage()}
label={_(msg`Clear all storage data`)}>
@@ -2,9 +2,10 @@ import React from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'
import {useAgent, useSession} from '#/state/session'
import {useDialogControl} from '#/components/Dialog'
import {ChangeEmailDialog} from '#/components/dialogs/ChangeEmailDialog'
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
import * as Prompt from '#/components/Prompt'
import {DisableEmail2FADialog} from './DisableEmail2FADialog'
import * as SettingsList from './SettingsList'
@@ -12,9 +13,10 @@ import * as SettingsList from './SettingsList'
export function Email2FAToggle() {
const {_} = useLingui()
const {currentAccount} = useSession()
const {openModal} = useModalControls()
const disableDialogControl = useDialogControl()
const enableDialogControl = useDialogControl()
const verifyEmailDialogControl = useDialogControl()
const changeEmailDialogControl = useDialogControl()
const agent = useAgent()
const enableEmailAuthFactor = React.useCallback(async () => {
@@ -35,15 +37,17 @@ export function Email2FAToggle() {
disableDialogControl.open()
} else {
if (!currentAccount.emailConfirmed) {
openModal({
name: 'verify-email',
onSuccess: enableDialogControl.open,
})
verifyEmailDialogControl.open()
return
}
enableDialogControl.open()
}
}, [currentAccount, enableDialogControl, openModal, disableDialogControl])
}, [
currentAccount,
enableDialogControl,
verifyEmailDialogControl,
disableDialogControl,
])
return (
<>
@@ -55,6 +59,18 @@ export function Email2FAToggle() {
onConfirm={enableEmailAuthFactor}
confirmButtonCta={_(msg`Enable`)}
/>
<VerifyEmailDialog
control={verifyEmailDialogControl}
changeEmailControl={changeEmailDialogControl}
onCloseAfterVerifying={enableDialogControl.open}
reasonText={_(
msg`You need to verify your email address before you can enable email 2FA.`,
)}
/>
<ChangeEmailDialog
control={changeEmailDialogControl}
verifyEmailControl={verifyEmailDialogControl}
/>
<SettingsList.BadgeButton
label={
currentAccount?.emailAuthFactor ? _(msg`Change`) : _(msg`Enable`)