about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2025-06-17 18:12:37 -0500
committerGitHub <noreply@github.com>2025-06-17 18:12:37 -0500
commit619fa0d0bbac80100aefeb926ca7098f0644d0d8 (patch)
tree40729c362c6412c88ba6c9887bdff1bf65891d7f /src
parent9cf457acf8495c1287e366f677e1516847e4d739 (diff)
downloadvoidsky-619fa0d0bbac80100aefeb926ca7098f0644d0d8.tar.zst
Delete some old dialogs (#8512)
* Delete old EditProfile dialog

* Delete old email verification dialogs
Diffstat (limited to 'src')
-rw-r--r--src/components/dialogs/ChangeEmailDialog.tsx259
-rw-r--r--src/components/dialogs/VerifyEmailDialog.tsx360
-rw-r--r--src/view/com/modals/EditProfile.tsx335
3 files changed, 0 insertions, 954 deletions
diff --git a/src/components/dialogs/ChangeEmailDialog.tsx b/src/components/dialogs/ChangeEmailDialog.tsx
deleted file mode 100644
index 93397bae9..000000000
--- a/src/components/dialogs/ChangeEmailDialog.tsx
+++ /dev/null
@@ -1,259 +0,0 @@
-import {useState} from 'react'
-import {View} from 'react-native'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-
-import {cleanError} from '#/lib/strings/errors'
-import {useAgent, useSession} from '#/state/session'
-import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
-import {atoms as a, useBreakpoints, web} from '#/alf'
-import {Button, ButtonText} from '#/components/Button'
-import * as Dialog from '#/components/Dialog'
-import * as TextField from '#/components/forms/TextField'
-import {Loader} from '#/components/Loader'
-import {Text} from '#/components/Typography'
-
-export function ChangeEmailDialog({
-  control,
-  verifyEmailControl,
-}: {
-  control: Dialog.DialogControlProps
-  verifyEmailControl: Dialog.DialogControlProps
-}) {
-  return (
-    <Dialog.Outer control={control}>
-      <Dialog.Handle />
-      <Inner verifyEmailControl={verifyEmailControl} />
-    </Dialog.Outer>
-  )
-}
-
-export function Inner({
-  verifyEmailControl,
-}: {
-  verifyEmailControl: Dialog.DialogControlProps
-}) {
-  const {_} = useLingui()
-  const {currentAccount} = useSession()
-  const agent = useAgent()
-  const control = Dialog.useDialogContext()
-  const {gtMobile} = useBreakpoints()
-
-  const [currentStep, setCurrentStep] = useState<
-    'StepOne' | 'StepTwo' | 'StepThree'
-  >('StepOne')
-  const [email, setEmail] = useState('')
-  const [confirmationCode, setConfirmationCode] = useState('')
-  const [isProcessing, setIsProcessing] = useState(false)
-  const [error, setError] = useState('')
-
-  const currentEmail = currentAccount?.email || '(no email)'
-  const uiStrings = {
-    StepOne: {
-      title: _(msg`Change Your Email`),
-      message: '',
-    },
-    StepTwo: {
-      title: _(msg`Security Step Required`),
-      message: _(
-        msg`An email has been sent to your previous address, ${currentEmail}. It includes a confirmation code which you can enter below.`,
-      ),
-    },
-    StepThree: {
-      title: _(msg`Email Updated!`),
-      message: _(
-        msg`Your email address has been updated but it is not yet verified. As a next step, please verify your new email.`,
-      ),
-    },
-  }
-
-  const onRequestChange = async () => {
-    if (email === currentAccount?.email) {
-      setError(
-        _(
-          msg`The email address you entered is the same as your current email address.`,
-        ),
-      )
-      return
-    }
-    setError('')
-    setIsProcessing(true)
-    try {
-      const res = await agent.com.atproto.server.requestEmailUpdate()
-      if (res.data.tokenRequired) {
-        setCurrentStep('StepTwo')
-      } else {
-        await agent.com.atproto.server.updateEmail({email: email.trim()})
-        await agent.resumeSession(agent.session!)
-        setCurrentStep('StepThree')
-      }
-    } catch (e) {
-      setError(cleanError(String(e)))
-    } finally {
-      setIsProcessing(false)
-    }
-  }
-
-  const onConfirm = async () => {
-    setError('')
-    setIsProcessing(true)
-    try {
-      await agent.com.atproto.server.updateEmail({
-        email: email.trim(),
-        token: confirmationCode.trim(),
-      })
-      await agent.resumeSession(agent.session!)
-      setCurrentStep('StepThree')
-    } catch (e) {
-      setError(cleanError(String(e)))
-    } finally {
-      setIsProcessing(false)
-    }
-  }
-
-  const onVerify = async () => {
-    control.close(() => {
-      verifyEmailControl.open()
-    })
-  }
-
-  return (
-    <Dialog.ScrollableInner
-      label={_(msg`Verify email dialog`)}
-      style={web({maxWidth: 450})}>
-      <Dialog.Close />
-      <View style={[a.gap_xl]}>
-        <View style={[a.gap_sm]}>
-          <Text style={[a.font_heavy, a.text_2xl]}>
-            {uiStrings[currentStep].title}
-          </Text>
-          {error ? (
-            <View style={[a.rounded_sm, a.overflow_hidden]}>
-              <ErrorMessage message={error} />
-            </View>
-          ) : null}
-          {currentStep === 'StepOne' ? (
-            <View>
-              <TextField.LabelText>
-                <Trans>Enter your new email address below.</Trans>
-              </TextField.LabelText>
-              <TextField.Root>
-                <TextField.Input
-                  label={_(msg`New email address`)}
-                  placeholder={_(msg`alice@example.com`)}
-                  defaultValue={email}
-                  onChangeText={setEmail}
-                  keyboardType="email-address"
-                  autoComplete="email"
-                />
-              </TextField.Root>
-            </View>
-          ) : (
-            <Text style={[a.text_md, a.leading_snug]}>
-              {uiStrings[currentStep].message}
-            </Text>
-          )}
-        </View>
-        {currentStep === 'StepTwo' ? (
-          <View>
-            <TextField.LabelText>
-              <Trans>Confirmation code</Trans>
-            </TextField.LabelText>
-            <TextField.Root>
-              <TextField.Input
-                label={_(msg`Confirmation code`)}
-                placeholder="XXXXX-XXXXX"
-                onChangeText={setConfirmationCode}
-              />
-            </TextField.Root>
-          </View>
-        ) : null}
-        <View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}>
-          {currentStep === 'StepOne' ? (
-            <>
-              <Button
-                label={_(msg`Request change`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                disabled={isProcessing}
-                onPress={onRequestChange}>
-                <ButtonText>
-                  <Trans>Request change</Trans>
-                </ButtonText>
-                {isProcessing ? (
-                  <Loader size="sm" style={[{color: 'white'}]} />
-                ) : null}
-              </Button>
-              <Button
-                label={_(msg`I have a code`)}
-                variant="solid"
-                color="secondary"
-                size="large"
-                disabled={isProcessing}
-                onPress={() => setCurrentStep('StepTwo')}>
-                <ButtonText>
-                  <Trans>I have a code</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : currentStep === 'StepTwo' ? (
-            <>
-              <Button
-                label={_(msg`Confirm`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                disabled={isProcessing}
-                onPress={onConfirm}>
-                <ButtonText>
-                  <Trans>Confirm</Trans>
-                </ButtonText>
-                {isProcessing ? (
-                  <Loader size="sm" style={[{color: 'white'}]} />
-                ) : null}
-              </Button>
-              <Button
-                label={_(msg`Resend email`)}
-                variant="solid"
-                color="secondary"
-                size="large"
-                disabled={isProcessing}
-                onPress={() => {
-                  setConfirmationCode('')
-                  setCurrentStep('StepOne')
-                }}>
-                <ButtonText>
-                  <Trans>Resend email</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : currentStep === 'StepThree' ? (
-            <>
-              <Button
-                label={_(msg`Verify email`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                onPress={onVerify}>
-                <ButtonText>
-                  <Trans>Verify email</Trans>
-                </ButtonText>
-              </Button>
-              <Button
-                label={_(msg`Close`)}
-                variant="solid"
-                color="secondary"
-                size="large"
-                onPress={() => control.close()}>
-                <ButtonText>
-                  <Trans>Close</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : null}
-        </View>
-      </View>
-    </Dialog.ScrollableInner>
-  )
-}
diff --git a/src/components/dialogs/VerifyEmailDialog.tsx b/src/components/dialogs/VerifyEmailDialog.tsx
deleted file mode 100644
index b8d1cd192..000000000
--- a/src/components/dialogs/VerifyEmailDialog.tsx
+++ /dev/null
@@ -1,360 +0,0 @@
-import {useState} from 'react'
-import {View} from 'react-native'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-
-import {cleanError} from '#/lib/strings/errors'
-import {logger} from '#/logger'
-import {useAgent, useSession} from '#/state/session'
-import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
-import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
-import {Button, ButtonText} from '#/components/Button'
-import * as Dialog from '#/components/Dialog'
-import * as TextField from '#/components/forms/TextField'
-import {Envelope_Filled_Stroke2_Corner0_Rounded as EnvelopeIcon} from '#/components/icons/Envelope'
-import {InlineLinkText} from '#/components/Link'
-import {Loader} from '#/components/Loader'
-import {Text} from '#/components/Typography'
-import {ChangeEmailDialog} from './ChangeEmailDialog'
-
-export function VerifyEmailDialog({
-  control,
-  onCloseWithoutVerifying,
-  onCloseAfterVerifying,
-  reasonText,
-  changeEmailControl,
-  reminder,
-}: {
-  control: Dialog.DialogControlProps
-  onCloseWithoutVerifying?: () => void
-  onCloseAfterVerifying?: () => void
-  reasonText?: string
-  /**
-   * if a changeEmailControl for a ChangeEmailDialog is not provided,
-   * this component will create one for you. Using this prop
-   * helps reduce duplication, since these dialogs are often used together.
-   */
-  changeEmailControl?: Dialog.DialogControlProps
-  reminder?: boolean
-}) {
-  const agent = useAgent()
-  const fallbackChangeEmailControl = Dialog.useDialogControl()
-
-  const [didVerify, setDidVerify] = useState(false)
-
-  return (
-    <>
-      <Dialog.Outer
-        control={control}
-        onClose={async () => {
-          if (!didVerify) {
-            onCloseWithoutVerifying?.()
-            return
-          }
-
-          try {
-            await agent.resumeSession(agent.session!)
-            onCloseAfterVerifying?.()
-          } catch (e: unknown) {
-            logger.error(String(e))
-            return
-          }
-        }}>
-        <Dialog.Handle />
-        <Inner
-          setDidVerify={setDidVerify}
-          reasonText={reasonText}
-          changeEmailControl={changeEmailControl ?? fallbackChangeEmailControl}
-          reminder={reminder}
-        />
-      </Dialog.Outer>
-      {!changeEmailControl && (
-        <ChangeEmailDialog
-          control={fallbackChangeEmailControl}
-          verifyEmailControl={control}
-        />
-      )}
-    </>
-  )
-}
-
-export function Inner({
-  setDidVerify,
-  reasonText,
-  changeEmailControl,
-  reminder,
-}: {
-  setDidVerify: (value: boolean) => void
-  reasonText?: string
-  changeEmailControl: Dialog.DialogControlProps
-  reminder?: boolean
-}) {
-  const control = Dialog.useDialogContext()
-  const {_} = useLingui()
-  const {currentAccount} = useSession()
-  const agent = useAgent()
-  const {gtMobile} = useBreakpoints()
-  const t = useTheme()
-
-  const [currentStep, setCurrentStep] = useState<
-    'Reminder' | 'StepOne' | 'StepTwo' | 'StepThree'
-  >(reminder ? 'Reminder' : 'StepOne')
-  const [confirmationCode, setConfirmationCode] = useState('')
-  const [isProcessing, setIsProcessing] = useState(false)
-  const [error, setError] = useState('')
-
-  const uiStrings = {
-    Reminder: {
-      title: _(msg`Please Verify Your Email`),
-      message: _(
-        msg`Your email has not yet been verified. This is an important security step which we recommend.`,
-      ),
-    },
-    StepOne: {
-      title: _(msg`Verify Your Email`),
-      message: '',
-    },
-    StepTwo: {
-      title: _(msg`Enter Code`),
-      message: _(
-        msg`An email has been sent! Please enter the confirmation code included in the email below.`,
-      ),
-    },
-    StepThree: {
-      title: _(msg`Success!`),
-      message: _(msg`Thank you! Your email has been successfully verified.`),
-    },
-  }
-
-  const onSendEmail = async () => {
-    setError('')
-    setIsProcessing(true)
-    try {
-      await agent.com.atproto.server.requestEmailConfirmation()
-      setCurrentStep('StepTwo')
-    } catch (e: unknown) {
-      setError(cleanError(e))
-    } finally {
-      setIsProcessing(false)
-    }
-  }
-
-  const onVerifyEmail = async () => {
-    setError('')
-    setIsProcessing(true)
-    try {
-      await agent.com.atproto.server.confirmEmail({
-        email: (currentAccount?.email || '').trim(),
-        token: confirmationCode.trim(),
-      })
-    } catch (e: unknown) {
-      setError(cleanError(String(e)))
-      setIsProcessing(false)
-      return
-    }
-
-    setIsProcessing(false)
-    setDidVerify(true)
-    setCurrentStep('StepThree')
-  }
-
-  return (
-    <Dialog.ScrollableInner
-      label={_(msg`Verify email dialog`)}
-      style={web({maxWidth: 450})}>
-      <View style={[a.gap_xl]}>
-        {currentStep === 'Reminder' && (
-          <View
-            style={[
-              a.rounded_sm,
-              a.align_center,
-              a.justify_center,
-              {height: 150},
-              t.atoms.bg_contrast_100,
-            ]}>
-            <EnvelopeIcon width={64} fill="white" />
-          </View>
-        )}
-        <View style={[a.gap_sm]}>
-          <Text style={[a.font_heavy, a.text_2xl]}>
-            {uiStrings[currentStep].title}
-          </Text>
-          {error ? (
-            <View style={[a.rounded_sm, a.overflow_hidden]}>
-              <ErrorMessage message={error} />
-            </View>
-          ) : null}
-          {currentStep === 'StepOne' ? (
-            <View>
-              {reasonText ? (
-                <View style={[a.gap_sm]}>
-                  <Text style={[a.text_md, a.leading_snug]}>{reasonText}</Text>
-                  <Text style={[a.text_md, a.leading_snug]}>
-                    Don't have access to{' '}
-                    <Text style={[a.text_md, a.leading_snug, a.font_bold]}>
-                      {currentAccount?.email}
-                    </Text>
-                    ?{' '}
-                    <InlineLinkText
-                      to="#"
-                      label={_(msg`Change email address`)}
-                      style={[a.text_md, a.leading_snug]}
-                      onPress={e => {
-                        e.preventDefault()
-                        control.close(() => {
-                          changeEmailControl.open()
-                        })
-                        return false
-                      }}>
-                      <Trans>Change your email address</Trans>
-                    </InlineLinkText>
-                    .
-                  </Text>
-                </View>
-              ) : (
-                <Text style={[a.text_md, a.leading_snug]}>
-                  <Trans>
-                    You'll receive an email at{' '}
-                    <Text style={[a.text_md, a.leading_snug, a.font_bold]}>
-                      {currentAccount?.email}
-                    </Text>{' '}
-                    to verify it's you.
-                  </Trans>{' '}
-                  <InlineLinkText
-                    to="#"
-                    label={_(msg`Change email address`)}
-                    style={[a.text_md, a.leading_snug]}
-                    onPress={e => {
-                      e.preventDefault()
-                      control.close(() => {
-                        changeEmailControl.open()
-                      })
-                      return false
-                    }}>
-                    <Trans>Need to change it?</Trans>
-                  </InlineLinkText>
-                </Text>
-              )}
-            </View>
-          ) : (
-            <Text style={[a.text_md, a.leading_snug]}>
-              {uiStrings[currentStep].message}
-            </Text>
-          )}
-        </View>
-        {currentStep === 'StepTwo' ? (
-          <View>
-            <TextField.LabelText>
-              <Trans>Confirmation Code</Trans>
-            </TextField.LabelText>
-            <TextField.Root>
-              <TextField.Input
-                label={_(msg`Confirmation code`)}
-                placeholder="XXXXX-XXXXX"
-                onChangeText={setConfirmationCode}
-              />
-            </TextField.Root>
-          </View>
-        ) : null}
-        <View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}>
-          {currentStep === 'Reminder' ? (
-            <>
-              <Button
-                label={_(msg`Get started`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                onPress={() => setCurrentStep('StepOne')}>
-                <ButtonText>
-                  <Trans>Get started</Trans>
-                </ButtonText>
-              </Button>
-              <Button
-                label={_(msg`Maybe later`)}
-                accessibilityHint={_(msg`Snoozes the reminder`)}
-                variant="ghost"
-                color="secondary"
-                size="large"
-                disabled={isProcessing}
-                onPress={() => control.close()}>
-                <ButtonText>
-                  <Trans>Maybe later</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : currentStep === 'StepOne' ? (
-            <>
-              <Button
-                label={_(msg`Send confirmation email`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                disabled={isProcessing}
-                onPress={onSendEmail}>
-                <ButtonText>
-                  <Trans>Send confirmation</Trans>
-                </ButtonText>
-                {isProcessing ? (
-                  <Loader size="sm" style={[{color: 'white'}]} />
-                ) : null}
-              </Button>
-              <Button
-                label={_(msg`I have a code`)}
-                variant="solid"
-                color="secondary"
-                size="large"
-                disabled={isProcessing}
-                onPress={() => setCurrentStep('StepTwo')}>
-                <ButtonText>
-                  <Trans>I have a code</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : currentStep === 'StepTwo' ? (
-            <>
-              <Button
-                label={_(msg`Confirm`)}
-                variant="solid"
-                color="primary"
-                size="large"
-                disabled={isProcessing}
-                onPress={onVerifyEmail}>
-                <ButtonText>
-                  <Trans>Confirm</Trans>
-                </ButtonText>
-                {isProcessing ? (
-                  <Loader size="sm" style={[{color: 'white'}]} />
-                ) : null}
-              </Button>
-              <Button
-                label={_(msg`Resend email`)}
-                variant="solid"
-                color="secondary"
-                size="large"
-                disabled={isProcessing}
-                onPress={() => {
-                  setConfirmationCode('')
-                  setCurrentStep('StepOne')
-                }}>
-                <ButtonText>
-                  <Trans>Resend email</Trans>
-                </ButtonText>
-              </Button>
-            </>
-          ) : currentStep === 'StepThree' ? (
-            <Button
-              label={_(msg`Close`)}
-              variant="solid"
-              color="primary"
-              size="large"
-              onPress={() => control.close()}>
-              <ButtonText>
-                <Trans>Close</Trans>
-              </ButtonText>
-            </Button>
-          ) : null}
-        </View>
-      </View>
-    </Dialog.ScrollableInner>
-  )
-}
diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx
deleted file mode 100644
index cb1552fe5..000000000
--- a/src/view/com/modals/EditProfile.tsx
+++ /dev/null
@@ -1,335 +0,0 @@
-import {useCallback, useState} from 'react'
-import {
-  ActivityIndicator,
-  KeyboardAvoidingView,
-  ScrollView,
-  StyleSheet,
-  TextInput,
-  TouchableOpacity,
-  View,
-} from 'react-native'
-import Animated, {FadeOut} from 'react-native-reanimated'
-import {LinearGradient} from 'expo-linear-gradient'
-import {type AppBskyActorDefs} from '@atproto/api'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-
-import {MAX_DESCRIPTION, MAX_DISPLAY_NAME, urls} from '#/lib/constants'
-import {usePalette} from '#/lib/hooks/usePalette'
-import {compressIfNeeded} from '#/lib/media/manip'
-import {type PickerImage} from '#/lib/media/picker.shared'
-import {cleanError} from '#/lib/strings/errors'
-import {enforceLen} from '#/lib/strings/helpers'
-import {colors, gradients, s} from '#/lib/styles'
-import {useTheme} from '#/lib/ThemeContext'
-import {logger} from '#/logger'
-import {isWeb} from '#/platform/detection'
-import {useModalControls} from '#/state/modals'
-import {useProfileUpdateMutation} from '#/state/queries/profile'
-import {Text} from '#/view/com/util/text/Text'
-import * as Toast from '#/view/com/util/Toast'
-import {EditableUserAvatar} from '#/view/com/util/UserAvatar'
-import {UserBanner} from '#/view/com/util/UserBanner'
-import {Admonition} from '#/components/Admonition'
-import {InlineLinkText} from '#/components/Link'
-import {useSimpleVerificationState} from '#/components/verification'
-import {ErrorMessage} from '../util/error/ErrorMessage'
-
-const AnimatedTouchableOpacity =
-  Animated.createAnimatedComponent(TouchableOpacity)
-
-export const snapPoints = ['fullscreen']
-
-export function Component({
-  profile,
-  onUpdate,
-}: {
-  profile: AppBskyActorDefs.ProfileViewDetailed
-  onUpdate?: () => void
-}) {
-  const pal = usePalette('default')
-  const theme = useTheme()
-  const {_} = useLingui()
-  const {closeModal} = useModalControls()
-  const updateMutation = useProfileUpdateMutation()
-  const [imageError, setImageError] = useState<string>('')
-  const initialDisplayName = profile.displayName || ''
-  const [displayName, setDisplayName] = useState<string>(
-    profile.displayName || '',
-  )
-  const [description, setDescription] = useState<string>(
-    profile.description || '',
-  )
-  const [userBanner, setUserBanner] = useState<string | undefined | null>(
-    profile.banner,
-  )
-  const [userAvatar, setUserAvatar] = useState<string | undefined | null>(
-    profile.avatar,
-  )
-  const [newUserBanner, setNewUserBanner] = useState<
-    PickerImage | undefined | null
-  >()
-  const [newUserAvatar, setNewUserAvatar] = useState<
-    PickerImage | undefined | null
-  >()
-  const onPressCancel = () => {
-    closeModal()
-  }
-  const onSelectNewAvatar = useCallback(
-    async (img: PickerImage | null) => {
-      setImageError('')
-      if (img === null) {
-        setNewUserAvatar(null)
-        setUserAvatar(null)
-        return
-      }
-      try {
-        const finalImg = await compressIfNeeded(img, 1000000)
-        setNewUserAvatar(finalImg)
-        setUserAvatar(finalImg.path)
-      } catch (e: any) {
-        setImageError(cleanError(e))
-      }
-    },
-    [setNewUserAvatar, setUserAvatar, setImageError],
-  )
-
-  const onSelectNewBanner = useCallback(
-    async (img: PickerImage | null) => {
-      setImageError('')
-      if (!img) {
-        setNewUserBanner(null)
-        setUserBanner(null)
-        return
-      }
-      try {
-        const finalImg = await compressIfNeeded(img, 1000000)
-        setNewUserBanner(finalImg)
-        setUserBanner(finalImg.path)
-      } catch (e: any) {
-        setImageError(cleanError(e))
-      }
-    },
-    [setNewUserBanner, setUserBanner, setImageError],
-  )
-
-  const onPressSave = useCallback(async () => {
-    setImageError('')
-    try {
-      await updateMutation.mutateAsync({
-        profile,
-        updates: {
-          displayName,
-          description,
-        },
-        newUserAvatar,
-        newUserBanner,
-      })
-      Toast.show(_(msg({message: 'Profile updated', context: 'toast'})))
-      onUpdate?.()
-      closeModal()
-    } catch (e: any) {
-      logger.error('Failed to update user profile', {message: String(e)})
-    }
-  }, [
-    updateMutation,
-    profile,
-    onUpdate,
-    closeModal,
-    displayName,
-    description,
-    newUserAvatar,
-    newUserBanner,
-    setImageError,
-    _,
-  ])
-  const verification = useSimpleVerificationState({
-    profile,
-  })
-
-  return (
-    <KeyboardAvoidingView style={s.flex1} behavior="height">
-      <ScrollView style={[pal.view]} testID="editProfileModal">
-        <Text style={[styles.title, pal.text]}>
-          <Trans>Edit my profile</Trans>
-        </Text>
-        <View style={styles.photos}>
-          <UserBanner
-            banner={userBanner}
-            onSelectNewBanner={onSelectNewBanner}
-          />
-          <View style={[styles.avi, {borderColor: pal.colors.background}]}>
-            <EditableUserAvatar
-              size={80}
-              avatar={userAvatar}
-              onSelectNewAvatar={onSelectNewAvatar}
-            />
-          </View>
-        </View>
-        {updateMutation.isError && (
-          <View style={styles.errorContainer}>
-            <ErrorMessage message={cleanError(updateMutation.error)} />
-          </View>
-        )}
-        {imageError !== '' && (
-          <View style={styles.errorContainer}>
-            <ErrorMessage message={imageError} />
-          </View>
-        )}
-        <View style={styles.form}>
-          <View>
-            <Text style={[styles.label, pal.text]}>
-              <Trans>Display Name</Trans>
-            </Text>
-            <TextInput
-              testID="editProfileDisplayNameInput"
-              style={[styles.textInput, pal.border, pal.text]}
-              placeholder={_(msg`e.g. Alice Roberts`)}
-              placeholderTextColor={colors.gray4}
-              value={displayName}
-              onChangeText={v =>
-                setDisplayName(enforceLen(v, MAX_DISPLAY_NAME))
-              }
-              accessible={true}
-              accessibilityLabel={_(msg`Display name`)}
-              accessibilityHint={_(msg`Edit your display name`)}
-            />
-
-            {verification.isVerified &&
-              verification.role === 'default' &&
-              displayName !== initialDisplayName && (
-                <View style={{paddingTop: 8}}>
-                  <Admonition type="error">
-                    <Trans>
-                      You are verified. You will lose your verification status
-                      if you change your display name.{' '}
-                      <InlineLinkText
-                        label={_(msg`Learn more`)}
-                        to={urls.website.blog.initialVerificationAnnouncement}>
-                        <Trans>Learn more.</Trans>
-                      </InlineLinkText>
-                    </Trans>
-                  </Admonition>
-                </View>
-              )}
-          </View>
-          <View style={s.pb10}>
-            <Text style={[styles.label, pal.text]}>
-              <Trans>Description</Trans>
-            </Text>
-            <TextInput
-              testID="editProfileDescriptionInput"
-              style={[styles.textArea, pal.border, pal.text]}
-              placeholder={_(msg`e.g. Artist, dog-lover, and avid reader.`)}
-              placeholderTextColor={colors.gray4}
-              keyboardAppearance={theme.colorScheme}
-              multiline
-              value={description}
-              onChangeText={v => setDescription(enforceLen(v, MAX_DESCRIPTION))}
-              accessible={true}
-              accessibilityLabel={_(msg`Description`)}
-              accessibilityHint={_(msg`Edit your profile description`)}
-            />
-          </View>
-          {updateMutation.isPending ? (
-            <View style={[styles.btn, s.mt10, {backgroundColor: colors.gray2}]}>
-              <ActivityIndicator />
-            </View>
-          ) : (
-            <TouchableOpacity
-              testID="editProfileSaveBtn"
-              style={s.mt10}
-              onPress={onPressSave}
-              accessibilityRole="button"
-              accessibilityLabel={_(msg`Save`)}
-              accessibilityHint={_(msg`Saves any changes to your profile`)}>
-              <LinearGradient
-                colors={[gradients.blueLight.start, gradients.blueLight.end]}
-                start={{x: 0, y: 0}}
-                end={{x: 1, y: 1}}
-                style={[styles.btn]}>
-                <Text style={[s.white, s.bold]}>
-                  <Trans>Save Changes</Trans>
-                </Text>
-              </LinearGradient>
-            </TouchableOpacity>
-          )}
-          {!updateMutation.isPending && (
-            <AnimatedTouchableOpacity
-              exiting={!isWeb ? FadeOut : undefined}
-              testID="editProfileCancelBtn"
-              style={s.mt5}
-              onPress={onPressCancel}
-              accessibilityRole="button"
-              accessibilityLabel={_(msg`Cancel profile editing`)}
-              accessibilityHint=""
-              onAccessibilityEscape={onPressCancel}>
-              <View style={[styles.btn]}>
-                <Text style={[s.black, s.bold, pal.text]}>
-                  <Trans>Cancel</Trans>
-                </Text>
-              </View>
-            </AnimatedTouchableOpacity>
-          )}
-        </View>
-      </ScrollView>
-    </KeyboardAvoidingView>
-  )
-}
-
-const styles = StyleSheet.create({
-  title: {
-    textAlign: 'center',
-    fontWeight: '600',
-    fontSize: 24,
-    marginBottom: 18,
-  },
-  label: {
-    fontWeight: '600',
-    paddingHorizontal: 4,
-    paddingBottom: 4,
-    marginTop: 20,
-  },
-  form: {
-    paddingHorizontal: 14,
-  },
-  textInput: {
-    borderWidth: 1,
-    borderRadius: 6,
-    paddingHorizontal: 14,
-    paddingVertical: 10,
-    fontSize: 16,
-  },
-  textArea: {
-    borderWidth: 1,
-    borderRadius: 6,
-    paddingHorizontal: 12,
-    paddingTop: 10,
-    fontSize: 16,
-    height: 120,
-    textAlignVertical: 'top',
-  },
-  btn: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    justifyContent: 'center',
-    width: '100%',
-    borderRadius: 32,
-    padding: 10,
-    marginBottom: 10,
-  },
-  avi: {
-    position: 'absolute',
-    top: 80,
-    left: 24,
-    width: 84,
-    height: 84,
-    borderWidth: 2,
-    borderRadius: 42,
-  },
-  photos: {
-    marginBottom: 36,
-    marginHorizontal: -14,
-  },
-  errorContainer: {marginTop: 20},
-})