diff --git a/src/languages/en.js b/src/languages/en.js index a47074925c0c..ead830dfc8e6 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -776,6 +776,16 @@ export default { linkSent: 'Link sent!', succesfullyUnlinkedLogin: 'Secondary login successfully unlinked!', }, + emailDeliveryFailurePage: { + ourEmailProvider: ({login}) => `Our email provider has temporarily suspended emails to ${login} due to delivery issues. To unblock your login, please follow these steps:`, + confirmThat: ({login}) => `Confirm that ${login} is spelled correctly and is a real, deliverable email address. `, + emailAliases: 'Email aliases such as "expenses@domain.com" must have access to their own email inbox for it to be a valid Expensify login.', + ensureYourEmailClient: 'Ensure your email client allows expensify.com emails. ', + youCanFindDirections: 'You can find directions on how to complete this step ', + helpConfigure: ' but you may need your IT department to help configure your email settings.', + onceTheAbove: 'Once the above steps are completed, please reach out to ', + toUnblock: ' to unblock your login.', + }, detailsPage: { localTime: 'Local time', }, diff --git a/src/languages/es.js b/src/languages/es.js index e81ad55dc1d8..7ec2b2fa1d26 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -778,6 +778,18 @@ export default { linkSent: '¡Enlace enviado!', succesfullyUnlinkedLogin: '¡Nombre de usuario secundario desvinculado correctamente!', }, + emailDeliveryFailurePage: { + ourEmailProvider: ({login}) => + `Nuestro proveedor de correo electrónico ha suspendido temporalmente los correos electrónicos a ${login} debido a problemas de entrega. Para desbloquear el inicio de sesión, sigue estos pasos:`, + confirmThat: ({login}) => `Confirma que ${login} está escrito correctamente y que es una dirección de correo electrónico real que puede recibir correos. `, + emailAliases: + 'Los alias de correo electrónico como "expenses@domain.com" deben tener acceso a su propia bandeja de entrada de correo electrónico para que sea un inicio de sesión válido de Expensify.', + ensureYourEmailClient: 'Asegúrese de que su cliente de correo electrónico permita correos electrónicos de expensify.com. ', + youCanFindDirections: 'Puedes encontrar instrucciones sobre cómo completar este paso ', + helpConfigure: ', pero es posible que necesites que el departamento de informática te ayude a configurar los ajustes de correo electrónico.', + onceTheAbove: 'Una vez completados los pasos anteriores, ponte en contacto con ', + toUnblock: ' para desbloquear el inicio de sesión.', + }, detailsPage: { localTime: 'Hora local', }, diff --git a/src/pages/signin/EmailDeliveryFailurePage.js b/src/pages/signin/EmailDeliveryFailurePage.js new file mode 100644 index 000000000000..5d56980a2b97 --- /dev/null +++ b/src/pages/signin/EmailDeliveryFailurePage.js @@ -0,0 +1,97 @@ +import React, {useEffect} from 'react'; +import {Keyboard, View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import PropTypes from 'prop-types'; +import Str from 'expensify-common/lib/str'; +import styles from '../../styles/styles'; +import Text from '../../components/Text'; +import TextLink from '../../components/TextLink'; +import ONYXKEYS from '../../ONYXKEYS'; +import useLocalize from '../../hooks/useLocalize'; +import useKeyboardState from '../../hooks/useKeyboardState'; +import redirectToSignIn from '../../libs/actions/SignInRedirect'; +import CONST from '../../CONST'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; + +const propTypes = { + /* Onyx Props */ + + /** The credentials of the logged in person */ + credentials: PropTypes.shape({ + /** The email/phone the user logged in with */ + login: PropTypes.string, + }), +}; + +const defaultProps = { + credentials: {}, +}; + +function EmailDeliveryFailurePage(props) { + const {isKeyboardShown} = useKeyboardState(); + const {translate} = useLocalize(); + const login = Str.isSMSLogin(props.credentials.login) ? Str.removeSMSDomain(props.credentials.login) : props.credentials.login; + + // This view doesn't have a field for user input, so dismiss the device keyboard if shown + useEffect(() => { + if (!isKeyboardShown) { + return; + } + Keyboard.dismiss(); + }, [isKeyboardShown]); + + return ( + <> + + + {translate('emailDeliveryFailurePage.ourEmailProvider', {login})} + + {translate('emailDeliveryFailurePage.confirmThat', {login})} + {translate('emailDeliveryFailurePage.emailAliases')} + + + {translate('emailDeliveryFailurePage.ensureYourEmailClient')} + {translate('emailDeliveryFailurePage.youCanFindDirections')} + + {translate('common.here')} + + {translate('emailDeliveryFailurePage.helpConfigure')} + + + {translate('emailDeliveryFailurePage.onceTheAbove')} + + {CONST.EMAIL.CONCIERGE} + + {translate('emailDeliveryFailurePage.toUnblock')} + + + + + redirectToSignIn()} + accessibilityRole="button" + accessibilityLabel={translate('common.back')} + // disable hover dim for switch + hoverDimmingValue={1} + pressDimmingValue={0.2} + > + {translate('common.back')} + + + + ); +} + +EmailDeliveryFailurePage.propTypes = propTypes; +EmailDeliveryFailurePage.defaultProps = defaultProps; +EmailDeliveryFailurePage.displayName = 'EmailDeliveryFailurePage'; + +export default withOnyx({ + credentials: {key: ONYXKEYS.CREDENTIALS}, +})(EmailDeliveryFailurePage); diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js index 042837401751..308043f252b4 100644 --- a/src/pages/signin/SignInPage.js +++ b/src/pages/signin/SignInPage.js @@ -15,6 +15,7 @@ import ResendValidationForm from './ResendValidationForm'; import Performance from '../../libs/Performance'; import * as App from '../../libs/actions/App'; import UnlinkLoginForm from './UnlinkLoginForm'; +import EmailDeliveryFailurePage from './EmailDeliveryFailurePage'; import * as Localize from '../../libs/Localize'; import * as StyleUtils from '../../styles/StyleUtils'; import useLocalize from '../../hooks/useLocalize'; @@ -39,6 +40,9 @@ const propTypes = { /** Does this account require 2FA? */ requiresTwoFactorAuth: PropTypes.bool, + + /** Is this account having trouble receiving emails */ + hasEmailDeliveryFailure: PropTypes.bool, }), /** The credentials of the person signing in */ @@ -63,18 +67,23 @@ const defaultProps = { * @param {Boolean} isAccountValidated * @param {Boolean} didForgetPassword * @param {Boolean} canUsePasswordlessLogins + * @param {Boolean} hasEmailDeliveryFailure * @returns {Object} */ -function getRenderOptions({hasLogin, hasPassword, hasValidateCode, hasAccount, isPrimaryLogin, isAccountValidated, didForgetPassword, canUsePasswordlessLogins}) { +function getRenderOptions({hasLogin, hasPassword, hasValidateCode, hasAccount, isPrimaryLogin, isAccountValidated, didForgetPassword, canUsePasswordlessLogins, hasEmailDeliveryFailure}) { const shouldShowLoginForm = !hasLogin && !hasValidateCode; - const isUnvalidatedSecondaryLogin = hasLogin && !isPrimaryLogin && !isAccountValidated; - const shouldShowPasswordForm = hasLogin && isAccountValidated && !hasPassword && !didForgetPassword && !isUnvalidatedSecondaryLogin && !canUsePasswordlessLogins; - const shouldShowValidateCodeForm = hasAccount && (hasLogin || hasValidateCode) && !isUnvalidatedSecondaryLogin && canUsePasswordlessLogins; - const shouldShowResendValidationForm = hasLogin && (!isAccountValidated || didForgetPassword) && !isUnvalidatedSecondaryLogin && !canUsePasswordlessLogins; - const shouldShowWelcomeHeader = shouldShowLoginForm || shouldShowPasswordForm || shouldShowValidateCodeForm || isUnvalidatedSecondaryLogin; + const shouldShowEmailDeliveryFailurePage = hasLogin && hasEmailDeliveryFailure; + const isUnvalidatedSecondaryLogin = hasLogin && !isPrimaryLogin && !isAccountValidated && !shouldShowEmailDeliveryFailurePage; + const shouldShowPasswordForm = + hasLogin && isAccountValidated && !hasPassword && !didForgetPassword && !isUnvalidatedSecondaryLogin && !canUsePasswordlessLogins && !shouldShowEmailDeliveryFailurePage; + const shouldShowValidateCodeForm = hasAccount && (hasLogin || hasValidateCode) && !isUnvalidatedSecondaryLogin && canUsePasswordlessLogins && !shouldShowEmailDeliveryFailurePage; + const shouldShowResendValidationForm = + hasLogin && (!isAccountValidated || didForgetPassword) && !isUnvalidatedSecondaryLogin && !canUsePasswordlessLogins && !shouldShowEmailDeliveryFailurePage; + const shouldShowWelcomeHeader = shouldShowLoginForm || shouldShowPasswordForm || shouldShowValidateCodeForm || isUnvalidatedSecondaryLogin || shouldShowEmailDeliveryFailurePage; const shouldShowWelcomeText = shouldShowLoginForm || shouldShowPasswordForm || shouldShowValidateCodeForm; return { shouldShowLoginForm, + shouldShowEmailDeliveryFailurePage, shouldShowUnlinkLoginForm: isUnvalidatedSecondaryLogin, shouldShowPasswordForm, shouldShowValidateCodeForm, @@ -97,6 +106,7 @@ function SignInPage({credentials, account}) { const { shouldShowLoginForm, + shouldShowEmailDeliveryFailurePage, shouldShowUnlinkLoginForm, shouldShowPasswordForm, shouldShowValidateCodeForm, @@ -112,11 +122,12 @@ function SignInPage({credentials, account}) { isAccountValidated: Boolean(account.validated), didForgetPassword: Boolean(account.forgotPassword), canUsePasswordlessLogins, + hasEmailDeliveryFailure: Boolean(account.hasEmailDeliveryFailure), }); let welcomeHeader; let welcomeText; - if (shouldShowValidateCodeForm) { + if (shouldShowValidateCodeForm || shouldShowResendValidationForm) { if (account.requiresTwoFactorAuth) { // We will only know this after a user signs in successfully, without their 2FA code welcomeHeader = isSmallScreenWidth ? '' : translate('welcomeText.welcomeBack'); @@ -141,8 +152,13 @@ function SignInPage({credentials, account}) { } else if (shouldShowPasswordForm) { welcomeHeader = isSmallScreenWidth ? '' : translate('welcomeText.welcomeBack'); welcomeText = isSmallScreenWidth ? `${translate('welcomeText.welcomeBack')} ${translate('welcomeText.enterPassword')}` : translate('welcomeText.enterPassword'); - } else if (shouldShowUnlinkLoginForm) { + } else if (shouldShowUnlinkLoginForm || shouldShowEmailDeliveryFailurePage) { welcomeHeader = isSmallScreenWidth ? translate('login.hero.header') : translate('welcomeText.welcomeBack'); + + // Don't show any welcome text if we're showing the user the email delivery failed view + if (shouldShowEmailDeliveryFailurePage) { + welcomeText = ''; + } } else if (!shouldShowResendValidationForm) { welcomeHeader = isSmallScreenWidth ? translate('login.hero.header') : translate('welcomeText.getStarted'); welcomeText = isSmallScreenWidth ? translate('welcomeText.getStarted') : ''; @@ -167,6 +183,7 @@ function SignInPage({credentials, account}) { {shouldShowValidateCodeForm ? : } {shouldShowResendValidationForm && } {shouldShowUnlinkLoginForm && } + {shouldShowEmailDeliveryFailurePage && } );