From 619fa0d0bbac80100aefeb926ca7098f0644d0d8 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 17 Jun 2025 18:12:37 -0500 Subject: Delete some old dialogs (#8512) * Delete old EditProfile dialog * Delete old email verification dialogs --- src/components/dialogs/ChangeEmailDialog.tsx | 259 ------------------- src/components/dialogs/VerifyEmailDialog.tsx | 360 --------------------------- src/view/com/modals/EditProfile.tsx | 335 ------------------------- 3 files changed, 954 deletions(-) delete mode 100644 src/components/dialogs/ChangeEmailDialog.tsx delete mode 100644 src/components/dialogs/VerifyEmailDialog.tsx delete mode 100644 src/view/com/modals/EditProfile.tsx (limited to 'src') 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 ( - - - - - ) -} - -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 ( - - - - - - {uiStrings[currentStep].title} - - {error ? ( - - - - ) : null} - {currentStep === 'StepOne' ? ( - - - Enter your new email address below. - - - - - - ) : ( - - {uiStrings[currentStep].message} - - )} - - {currentStep === 'StepTwo' ? ( - - - Confirmation code - - - - - - ) : null} - - {currentStep === 'StepOne' ? ( - <> - - - - ) : currentStep === 'StepTwo' ? ( - <> - - - - ) : currentStep === 'StepThree' ? ( - <> - - - - ) : null} - - - - ) -} 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 ( - <> - { - if (!didVerify) { - onCloseWithoutVerifying?.() - return - } - - try { - await agent.resumeSession(agent.session!) - onCloseAfterVerifying?.() - } catch (e: unknown) { - logger.error(String(e)) - return - } - }}> - - - - {!changeEmailControl && ( - - )} - - ) -} - -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 ( - - - {currentStep === 'Reminder' && ( - - - - )} - - - {uiStrings[currentStep].title} - - {error ? ( - - - - ) : null} - {currentStep === 'StepOne' ? ( - - {reasonText ? ( - - {reasonText} - - Don't have access to{' '} - - {currentAccount?.email} - - ?{' '} - { - e.preventDefault() - control.close(() => { - changeEmailControl.open() - }) - return false - }}> - Change your email address - - . - - - ) : ( - - - You'll receive an email at{' '} - - {currentAccount?.email} - {' '} - to verify it's you. - {' '} - { - e.preventDefault() - control.close(() => { - changeEmailControl.open() - }) - return false - }}> - Need to change it? - - - )} - - ) : ( - - {uiStrings[currentStep].message} - - )} - - {currentStep === 'StepTwo' ? ( - - - Confirmation Code - - - - - - ) : null} - - {currentStep === 'Reminder' ? ( - <> - - - - ) : currentStep === 'StepOne' ? ( - <> - - - - ) : currentStep === 'StepTwo' ? ( - <> - - - - ) : currentStep === 'StepThree' ? ( - - ) : null} - - - - ) -} 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('') - const initialDisplayName = profile.displayName || '' - const [displayName, setDisplayName] = useState( - profile.displayName || '', - ) - const [description, setDescription] = useState( - profile.description || '', - ) - const [userBanner, setUserBanner] = useState( - profile.banner, - ) - const [userAvatar, setUserAvatar] = useState( - 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 ( - - - - Edit my profile - - - - - - - - {updateMutation.isError && ( - - - - )} - {imageError !== '' && ( - - - - )} - - - - Display Name - - - 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 && ( - - - - You are verified. You will lose your verification status - if you change your display name.{' '} - - Learn more. - - - - - )} - - - - Description - - setDescription(enforceLen(v, MAX_DESCRIPTION))} - accessible={true} - accessibilityLabel={_(msg`Description`)} - accessibilityHint={_(msg`Edit your profile description`)} - /> - - {updateMutation.isPending ? ( - - - - ) : ( - - - - Save Changes - - - - )} - {!updateMutation.isPending && ( - - - - Cancel - - - - )} - - - - ) -} - -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}, -}) -- cgit 1.4.1