diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/auth/login/ForgotPasswordForm.tsx | 228 | ||||
-rw-r--r-- | src/view/com/auth/login/PasswordUpdatedForm.tsx | 48 | ||||
-rw-r--r-- | src/view/com/auth/login/SetNewPasswordForm.tsx | 211 | ||||
-rw-r--r-- | src/view/com/auth/login/styles.ts | 118 |
4 files changed, 0 insertions, 605 deletions
diff --git a/src/view/com/auth/login/ForgotPasswordForm.tsx b/src/view/com/auth/login/ForgotPasswordForm.tsx deleted file mode 100644 index 322da2b8f..000000000 --- a/src/view/com/auth/login/ForgotPasswordForm.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import React, {useState, useEffect} from 'react' -import { - ActivityIndicator, - Keyboard, - TextInput, - TouchableOpacity, - View, -} from 'react-native' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' -import {ComAtprotoServerDescribeServer} from '@atproto/api' -import * as EmailValidator from 'email-validator' -import {BskyAgent} from '@atproto/api' -import {useAnalytics} from 'lib/analytics/analytics' -import {Text} from '../../util/text/Text' -import {s} from 'lib/styles' -import {toNiceDomain} from 'lib/strings/url-helpers' -import {isNetworkError} from 'lib/strings/errors' -import {usePalette} from 'lib/hooks/usePalette' -import {useTheme} from 'lib/ThemeContext' -import {cleanError} from 'lib/strings/errors' -import {logger} from '#/logger' -import {Trans, msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {styles} from './styles' -import {useDialogControl} from '#/components/Dialog' - -import {ServerInputDialog} from '../server-input' - -type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema - -export const ForgotPasswordForm = ({ - error, - serviceUrl, - serviceDescription, - setError, - setServiceUrl, - onPressBack, - onEmailSent, -}: { - error: string - serviceUrl: string - serviceDescription: ServiceDescription | undefined - setError: (v: string) => void - setServiceUrl: (v: string) => void - onPressBack: () => void - onEmailSent: () => void -}) => { - const pal = usePalette('default') - const theme = useTheme() - const [isProcessing, setIsProcessing] = useState<boolean>(false) - const [email, setEmail] = useState<string>('') - const {screen} = useAnalytics() - const {_} = useLingui() - const serverInputControl = useDialogControl() - - useEffect(() => { - screen('Signin:ForgotPassword') - }, [screen]) - - const onPressSelectService = React.useCallback(() => { - serverInputControl.open() - Keyboard.dismiss() - }, [serverInputControl]) - - const onPressNext = async () => { - if (!EmailValidator.validate(email)) { - return setError(_(msg`Your email appears to be invalid.`)) - } - - setError('') - setIsProcessing(true) - - try { - const agent = new BskyAgent({service: serviceUrl}) - await agent.com.atproto.server.requestPasswordReset({email}) - onEmailSent() - } catch (e: any) { - const errMsg = e.toString() - logger.warn('Failed to request password reset', {error: e}) - setIsProcessing(false) - if (isNetworkError(e)) { - setError( - _( - msg`Unable to contact your service. Please check your Internet connection.`, - ), - ) - } else { - setError(cleanError(errMsg)) - } - } - } - - return ( - <> - <View> - <ServerInputDialog - control={serverInputControl} - onSelect={setServiceUrl} - /> - <Text type="title-lg" style={[pal.text, styles.screenTitle]}> - <Trans>Reset password</Trans> - </Text> - <Text type="md" style={[pal.text, styles.instructions]}> - <Trans> - Enter the email you used to create your account. We'll send you a - "reset code" so you can set a new password. - </Trans> - </Text> - <View - testID="forgotPasswordView" - style={[pal.borderDark, pal.view, styles.group]}> - <TouchableOpacity - testID="forgotPasswordSelectServiceButton" - style={[pal.borderDark, styles.groupContent, styles.noTopBorder]} - onPress={onPressSelectService} - accessibilityRole="button" - accessibilityLabel={_(msg`Hosting provider`)} - accessibilityHint={_( - msg`Sets hosting provider for password reset`, - )}> - <FontAwesomeIcon - icon="globe" - style={[pal.textLight, styles.groupContentIcon]} - /> - <Text style={[pal.text, styles.textInput]} numberOfLines={1}> - {toNiceDomain(serviceUrl)} - </Text> - <View style={[pal.btn, styles.textBtnFakeInnerBtn]}> - <FontAwesomeIcon - icon="pen" - size={12} - style={pal.text as FontAwesomeIconStyle} - /> - </View> - </TouchableOpacity> - <View style={[pal.borderDark, styles.groupContent]}> - <FontAwesomeIcon - icon="envelope" - style={[pal.textLight, styles.groupContentIcon]} - /> - <TextInput - testID="forgotPasswordEmail" - style={[pal.text, styles.textInput]} - placeholder={_(msg`Email address`)} - placeholderTextColor={pal.colors.textLight} - autoCapitalize="none" - autoFocus - autoCorrect={false} - keyboardAppearance={theme.colorScheme} - value={email} - onChangeText={setEmail} - editable={!isProcessing} - accessibilityLabel={_(msg`Email`)} - accessibilityHint={_(msg`Sets email for password reset`)} - /> - </View> - </View> - {error ? ( - <View style={styles.error}> - <View style={styles.errorIcon}> - <FontAwesomeIcon icon="exclamation" style={s.white} size={10} /> - </View> - <View style={s.flex1}> - <Text style={[s.white, s.bold]}>{error}</Text> - </View> - </View> - ) : undefined} - <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}> - <TouchableOpacity onPress={onPressBack} accessibilityRole="button"> - <Text type="xl" style={[pal.link, s.pl5]}> - <Trans>Back</Trans> - </Text> - </TouchableOpacity> - <View style={s.flex1} /> - {!serviceDescription || isProcessing ? ( - <ActivityIndicator /> - ) : !email ? ( - <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}> - <Trans>Next</Trans> - </Text> - ) : ( - <TouchableOpacity - testID="newPasswordButton" - onPress={onPressNext} - accessibilityRole="button" - accessibilityLabel={_(msg`Go to next`)} - accessibilityHint={_(msg`Navigates to the next screen`)}> - <Text type="xl-bold" style={[pal.link, s.pr5]}> - <Trans>Next</Trans> - </Text> - </TouchableOpacity> - )} - {!serviceDescription || isProcessing ? ( - <Text type="xl" style={[pal.textLight, s.pl10]}> - <Trans>Processing...</Trans> - </Text> - ) : undefined} - </View> - <View - style={[ - s.flexRow, - s.alignCenter, - s.mt20, - s.mb20, - pal.border, - s.borderBottom1, - {alignSelf: 'center', width: '90%'}, - ]} - /> - <View style={[s.flexRow, s.justifyCenter]}> - <TouchableOpacity - testID="skipSendEmailButton" - onPress={onEmailSent} - accessibilityRole="button" - accessibilityLabel={_(msg`Go to next`)} - accessibilityHint={_(msg`Navigates to the next screen`)}> - <Text type="xl" style={[pal.link, s.pr5]}> - <Trans>Already have a code?</Trans> - </Text> - </TouchableOpacity> - </View> - </View> - </> - ) -} diff --git a/src/view/com/auth/login/PasswordUpdatedForm.tsx b/src/view/com/auth/login/PasswordUpdatedForm.tsx deleted file mode 100644 index 71f750b14..000000000 --- a/src/view/com/auth/login/PasswordUpdatedForm.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, {useEffect} from 'react' -import {TouchableOpacity, View} from 'react-native' -import {useAnalytics} from 'lib/analytics/analytics' -import {Text} from '../../util/text/Text' -import {s} from 'lib/styles' -import {usePalette} from 'lib/hooks/usePalette' -import {styles} from './styles' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -export const PasswordUpdatedForm = ({ - onPressNext, -}: { - onPressNext: () => void -}) => { - const {screen} = useAnalytics() - const pal = usePalette('default') - const {_} = useLingui() - - useEffect(() => { - screen('Signin:PasswordUpdatedForm') - }, [screen]) - - return ( - <> - <View> - <Text type="title-lg" style={[pal.text, styles.screenTitle]}> - <Trans>Password updated!</Trans> - </Text> - <Text type="lg" style={[pal.text, styles.instructions]}> - <Trans>You can now sign in with your new password.</Trans> - </Text> - <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}> - <View style={s.flex1} /> - <TouchableOpacity - onPress={onPressNext} - accessibilityRole="button" - accessibilityLabel={_(msg`Close alert`)} - accessibilityHint={_(msg`Closes password update alert`)}> - <Text type="xl-bold" style={[pal.link, s.pr5]}> - <Trans>Okay</Trans> - </Text> - </TouchableOpacity> - </View> - </View> - </> - ) -} diff --git a/src/view/com/auth/login/SetNewPasswordForm.tsx b/src/view/com/auth/login/SetNewPasswordForm.tsx deleted file mode 100644 index 6d1584c86..000000000 --- a/src/view/com/auth/login/SetNewPasswordForm.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import React, {useState, useEffect} from 'react' -import { - ActivityIndicator, - TextInput, - TouchableOpacity, - View, -} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {BskyAgent} from '@atproto/api' -import {useAnalytics} from 'lib/analytics/analytics' -import {Text} from '../../util/text/Text' -import {s} from 'lib/styles' -import {isNetworkError} from 'lib/strings/errors' -import {usePalette} from 'lib/hooks/usePalette' -import {useTheme} from 'lib/ThemeContext' -import {cleanError} from 'lib/strings/errors' -import {checkAndFormatResetCode} from 'lib/strings/password' -import {logger} from '#/logger' -import {styles} from './styles' -import {Trans, msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -export const SetNewPasswordForm = ({ - error, - serviceUrl, - setError, - onPressBack, - onPasswordSet, -}: { - error: string - serviceUrl: string - setError: (v: string) => void - onPressBack: () => void - onPasswordSet: () => void -}) => { - const pal = usePalette('default') - const theme = useTheme() - const {screen} = useAnalytics() - const {_} = useLingui() - - useEffect(() => { - screen('Signin:SetNewPasswordForm') - }, [screen]) - - const [isProcessing, setIsProcessing] = useState<boolean>(false) - const [resetCode, setResetCode] = useState<string>('') - const [password, setPassword] = useState<string>('') - - const onPressNext = async () => { - // Check that the code is correct. We do this again just incase the user enters the code after their pw and we - // don't get to call onBlur first - const formattedCode = checkAndFormatResetCode(resetCode) - // TODO Better password strength check - if (!formattedCode || !password) { - setError( - _( - msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, - ), - ) - return - } - - setError('') - setIsProcessing(true) - - try { - const agent = new BskyAgent({service: serviceUrl}) - await agent.com.atproto.server.resetPassword({ - token: formattedCode, - password, - }) - onPasswordSet() - } catch (e: any) { - const errMsg = e.toString() - logger.warn('Failed to set new password', {error: e}) - setIsProcessing(false) - if (isNetworkError(e)) { - setError( - 'Unable to contact your service. Please check your Internet connection.', - ) - } else { - setError(cleanError(errMsg)) - } - } - } - - const onBlur = () => { - const formattedCode = checkAndFormatResetCode(resetCode) - if (!formattedCode) { - setError( - _( - msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, - ), - ) - return - } - setResetCode(formattedCode) - } - - return ( - <> - <View> - <Text type="title-lg" style={[pal.text, styles.screenTitle]}> - <Trans>Set new password</Trans> - </Text> - <Text type="lg" style={[pal.text, styles.instructions]}> - <Trans> - You will receive an email with a "reset code." Enter that code here, - then enter your new password. - </Trans> - </Text> - <View - testID="newPasswordView" - style={[pal.view, pal.borderDark, styles.group]}> - <View - style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}> - <FontAwesomeIcon - icon="ticket" - style={[pal.textLight, styles.groupContentIcon]} - /> - <TextInput - testID="resetCodeInput" - style={[pal.text, styles.textInput]} - placeholder={_(msg`Reset code`)} - placeholderTextColor={pal.colors.textLight} - autoCapitalize="none" - autoCorrect={false} - keyboardAppearance={theme.colorScheme} - autoComplete="off" - value={resetCode} - onChangeText={setResetCode} - onFocus={() => setError('')} - onBlur={onBlur} - editable={!isProcessing} - accessible={true} - accessibilityLabel={_(msg`Reset code`)} - accessibilityHint={_( - msg`Input code sent to your email for password reset`, - )} - /> - </View> - <View style={[pal.borderDark, styles.groupContent]}> - <FontAwesomeIcon - icon="lock" - style={[pal.textLight, styles.groupContentIcon]} - /> - <TextInput - testID="newPasswordInput" - style={[pal.text, styles.textInput]} - placeholder={_(msg`New password`)} - placeholderTextColor={pal.colors.textLight} - autoCapitalize="none" - autoCorrect={false} - autoComplete="new-password" - keyboardAppearance={theme.colorScheme} - secureTextEntry - value={password} - onChangeText={setPassword} - editable={!isProcessing} - accessible={true} - accessibilityLabel={_(msg`Password`)} - accessibilityHint={_(msg`Input new password`)} - /> - </View> - </View> - {error ? ( - <View style={styles.error}> - <View style={styles.errorIcon}> - <FontAwesomeIcon icon="exclamation" style={s.white} size={10} /> - </View> - <View style={s.flex1}> - <Text style={[s.white, s.bold]}>{error}</Text> - </View> - </View> - ) : undefined} - <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}> - <TouchableOpacity onPress={onPressBack} accessibilityRole="button"> - <Text type="xl" style={[pal.link, s.pl5]}> - <Trans>Back</Trans> - </Text> - </TouchableOpacity> - <View style={s.flex1} /> - {isProcessing ? ( - <ActivityIndicator /> - ) : !resetCode || !password ? ( - <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}> - <Trans>Next</Trans> - </Text> - ) : ( - <TouchableOpacity - testID="setNewPasswordButton" - // Check the code before running the callback - onPress={onPressNext} - accessibilityRole="button" - accessibilityLabel={_(msg`Go to next`)} - accessibilityHint={_(msg`Navigates to the next screen`)}> - <Text type="xl-bold" style={[pal.link, s.pr5]}> - <Trans>Next</Trans> - </Text> - </TouchableOpacity> - )} - {isProcessing ? ( - <Text type="xl" style={[pal.textLight, s.pl10]}> - <Trans>Updating...</Trans> - </Text> - ) : undefined} - </View> - </View> - </> - ) -} diff --git a/src/view/com/auth/login/styles.ts b/src/view/com/auth/login/styles.ts deleted file mode 100644 index 9dccc2803..000000000 --- a/src/view/com/auth/login/styles.ts +++ /dev/null @@ -1,118 +0,0 @@ -import {StyleSheet} from 'react-native' -import {colors} from 'lib/styles' -import {isWeb} from '#/platform/detection' - -export const styles = StyleSheet.create({ - screenTitle: { - marginBottom: 10, - marginHorizontal: 20, - }, - instructions: { - marginBottom: 20, - marginHorizontal: 20, - }, - group: { - borderWidth: 1, - borderRadius: 10, - marginBottom: 20, - marginHorizontal: 20, - }, - groupLabel: { - paddingHorizontal: 20, - paddingBottom: 5, - }, - groupContent: { - borderTopWidth: 1, - flexDirection: 'row', - alignItems: 'center', - }, - noTopBorder: { - borderTopWidth: 0, - }, - groupContentIcon: { - marginLeft: 10, - }, - account: { - borderTopWidth: 1, - paddingHorizontal: 20, - paddingVertical: 4, - }, - accountLast: { - borderBottomWidth: 1, - marginBottom: 20, - paddingVertical: 8, - }, - textInput: { - flex: 1, - width: '100%', - paddingVertical: 10, - paddingHorizontal: 12, - fontSize: 17, - letterSpacing: 0.25, - fontWeight: '400', - borderRadius: 10, - }, - textInputInnerBtn: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: 6, - paddingHorizontal: 8, - marginHorizontal: 6, - }, - textBtn: { - flexDirection: 'row', - flex: 1, - alignItems: 'center', - }, - textBtnLabel: { - flex: 1, - paddingVertical: 10, - paddingHorizontal: 12, - }, - textBtnFakeInnerBtn: { - flexDirection: 'row', - alignItems: 'center', - borderRadius: 6, - paddingVertical: 6, - paddingHorizontal: 8, - marginHorizontal: 6, - }, - accountText: { - flex: 1, - flexDirection: 'row', - alignItems: 'baseline', - paddingVertical: 10, - }, - accountTextOther: { - paddingLeft: 12, - }, - error: { - backgroundColor: colors.red4, - flexDirection: 'row', - alignItems: 'center', - marginTop: -5, - marginHorizontal: 20, - marginBottom: 15, - borderRadius: 8, - paddingHorizontal: 8, - paddingVertical: 8, - }, - errorIcon: { - borderWidth: 1, - borderColor: colors.white, - color: colors.white, - borderRadius: 30, - width: 16, - height: 16, - alignItems: 'center', - justifyContent: 'center', - marginRight: 5, - }, - dimmed: {opacity: 0.5}, - - maxHeight: { - // @ts-ignore web only -prf - maxHeight: isWeb ? '100vh' : undefined, - height: !isWeb ? '100%' : undefined, - }, -}) |