Files
bsky-social-app/src/view/com/auth/login/SetNewPasswordForm.tsx
T
2023-11-07 15:51:42 -08:00

182 lines
5.8 KiB
TypeScript

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 {RootStoreModel} from 'state/index'
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 {styles} from './styles'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
export const SetNewPasswordForm = ({
error,
serviceUrl,
setError,
onPressBack,
onPasswordSet,
}: {
store: RootStoreModel
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 () => {
setError('')
setIsProcessing(true)
try {
const agent = new BskyAgent({service: serviceUrl})
const token = resetCode.replace(/\s/g, '')
await agent.com.atproto.server.resetPassword({
token,
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))
}
}
}
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="Reset code"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
autoCorrect={false}
keyboardAppearance={theme.colorScheme}
autoFocus
value={resetCode}
onChangeText={setResetCode}
editable={!isProcessing}
accessible={true}
accessibilityLabel={_(msg`Reset code`)}
accessibilityHint="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="New password"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
autoCorrect={false}
keyboardAppearance={theme.colorScheme}
secureTextEntry
value={password}
onChangeText={setPassword}
editable={!isProcessing}
accessible={true}
accessibilityLabel={_(msg`Password`)}
accessibilityHint="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"
onPress={onPressNext}
accessibilityRole="button"
accessibilityLabel={_(msg`Go to next`)}
accessibilityHint="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>
</>
)
}