diff --git a/src/screens/Signup/StepInfo/index.tsx b/src/screens/Signup/StepInfo/index.tsx
index 18ba385288..a19a3ad4a9 100644
--- a/src/screens/Signup/StepInfo/index.tsx
+++ b/src/screens/Signup/StepInfo/index.tsx
@@ -75,22 +75,6 @@ export function StepInfo({
const emailChanged = prevEmailValueRef.current !== email
const password = passwordValueRef.current
- if (emailChanged && tldtsRef.current) {
- if (isEmailMaybeInvalid(email, tldtsRef.current)) {
- prevEmailValueRef.current = email
- setHasWarnedEmail(true)
- return dispatch({
- type: 'setError',
- value: _(
- msg`It looks like you may have entered your email address incorrectly. Are you sure it's right?`,
- ),
- })
- }
- } else if (hasWarnedEmail) {
- setHasWarnedEmail(false)
- }
- prevEmailValueRef.current = email
-
if (!is13(state.dateOfBirth)) {
return
}
@@ -99,24 +83,50 @@ export function StepInfo({
return dispatch({
type: 'setError',
value: _(msg`Please enter your invite code.`),
+ field: 'invite-code',
})
}
if (!email) {
return dispatch({
type: 'setError',
value: _(msg`Please enter your email.`),
+ field: 'email',
})
}
if (!EmailValidator.validate(email)) {
return dispatch({
type: 'setError',
value: _(msg`Your email appears to be invalid.`),
+ field: 'email',
})
}
+ if (emailChanged && tldtsRef.current) {
+ if (isEmailMaybeInvalid(email, tldtsRef.current)) {
+ prevEmailValueRef.current = email
+ setHasWarnedEmail(true)
+ return dispatch({
+ type: 'setError',
+ value: _(
+ msg`Please double-check that you have entered your email address correctly.`,
+ ),
+ })
+ }
+ } else if (hasWarnedEmail) {
+ setHasWarnedEmail(false)
+ }
+ prevEmailValueRef.current = email
if (!password) {
return dispatch({
type: 'setError',
value: _(msg`Please choose your password.`),
+ field: 'password',
+ })
+ }
+ if (password.length < 8) {
+ return dispatch({
+ type: 'setError',
+ value: _(msg`Your password must be at least 8 characters long.`),
+ field: 'password',
})
}
@@ -149,11 +159,17 @@ export function StepInfo({
Invite code
-
+
{
inviteCodeValueRef.current = value.trim()
+ if (
+ state.errorField === 'invite-code' &&
+ value.trim().length > 0
+ ) {
+ dispatch({type: 'clearError'})
+ }
}}
label={_(msg`Required for this provider`)}
defaultValue={state.inviteCode}
@@ -173,7 +189,7 @@ export function StepInfo({
Email
-
+
0 &&
+ EmailValidator.validate(value.trim())
+ ) {
+ dispatch({type: 'clearError'})
+ }
}}
label={_(msg`Enter your email address`)}
defaultValue={state.email}
@@ -201,13 +224,16 @@ export function StepInfo({
Password
-
+
{
passwordValueRef.current = value
+ if (state.errorField === 'password' && value.length >= 8) {
+ dispatch({type: 'clearError'})
+ }
}}
label={_(msg`Choose your password`)}
defaultValue={state.password}
@@ -219,6 +245,7 @@ export function StepInfo({
onSubmitEditing={native(() =>
birthdateInputRef.current?.focus(),
)}
+ passwordRules="minlength: 8;"
/>
diff --git a/src/screens/Signup/state.ts b/src/screens/Signup/state.ts
index 4addf35805..3daf36a9b4 100644
--- a/src/screens/Signup/state.ts
+++ b/src/screens/Signup/state.ts
@@ -31,6 +31,13 @@ type SubmitTask = {
mutableProcessed: boolean // OK to mutate assuming it's never read in render.
}
+type ErrorField =
+ | 'invite-code'
+ | 'email'
+ | 'handle'
+ | 'password'
+ | 'date-of-birth'
+
export type SignupState = {
hasPrev: boolean
activeStep: SignupStep
@@ -45,6 +52,7 @@ export type SignupState = {
handle: string
error: string
+ errorField?: ErrorField
isLoading: boolean
pendingSubmit: null | SubmitTask
@@ -62,7 +70,8 @@ export type SignupAction =
| {type: 'setDateOfBirth'; value: Date}
| {type: 'setInviteCode'; value: string}
| {type: 'setHandle'; value: string}
- | {type: 'setError'; value: string}
+ | {type: 'setError'; value: string; field?: ErrorField}
+ | {type: 'clearError'}
| {type: 'setIsLoading'; value: boolean}
| {type: 'submit'; task: SubmitTask}
@@ -80,6 +89,7 @@ export const initialState: SignupState = {
inviteCode: '',
error: '',
+ errorField: undefined,
isLoading: false,
pendingSubmit: null,
@@ -102,6 +112,7 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
next.activeStep--
next.error = ''
+ next.errorField = undefined
}
break
}
@@ -110,6 +121,7 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
next.activeStep++
next.error = ''
+ next.errorField = undefined
}
break
}
@@ -156,6 +168,12 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
}
case 'setError': {
next.error = a.value
+ next.errorField = a.field
+ break
+ }
+ case 'clearError': {
+ next.error = ''
+ next.errorField = undefined
break
}
case 'submit': {
diff --git a/src/view/com/modals/ChangePassword.tsx b/src/view/com/modals/ChangePassword.tsx
index d68b4e4530..9b96e7db0f 100644
--- a/src/view/com/modals/ChangePassword.tsx
+++ b/src/view/com/modals/ChangePassword.tsx
@@ -81,8 +81,7 @@ export function Component() {
const onChangePassword = async () => {
const formattedCode = checkAndFormatResetCode(resetCode)
- // TODO Better password strength check
- if (!formattedCode || !newPassword) {
+ if (!formattedCode) {
setError(
_(
msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`,
@@ -90,6 +89,16 @@ export function Component() {
)
return
}
+ if (!newPassword) {
+ setError(
+ _(msg`Please enter a password. It must be at least 8 characters long.`),
+ )
+ return
+ }
+ if (newPassword.length < 8) {
+ setError(_(msg`Password must be at least 8 characters long.`))
+ return
+ }
setError('')
setIsProcessing(true)
@@ -104,7 +113,9 @@ export function Component() {
logger.warn('Failed to set new password', {error: e})
if (isNetworkError(e)) {
setError(
- 'Unable to contact your service. Please check your Internet connection.',
+ _(
+ msg`Unable to contact your service. Please check your Internet connection.`,
+ ),
)
} else {
setError(cleanError(errMsg))