diff --git a/src/ROUTES.js b/src/ROUTES.js
index a5fd5b4188c3..2e4e452dbb35 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -183,4 +183,5 @@ export default {
isSubReportPageRoute: Boolean(lodashGet(pathSegments, 2)),
};
},
+ SIGNINMODAL: 'signinmodal'
};
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
index 518ff33b0ad4..2793d78795c9 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
@@ -733,6 +733,16 @@ const EditRequestStackNavigator = createModalStackNavigator([
},
]);
+const SignInModalStackNavigator = createModalStackNavigator([
+ {
+ getComponent: () => {
+ const SignInModal = require('../../../pages/signin/SignInModal').default;
+ return SignInModal;
+ },
+ name: 'SignIn_Root',
+ }
+]);
+
export {
MoneyRequestModalStackNavigator,
SplitDetailsModalStackNavigator,
@@ -755,4 +765,5 @@ export {
YearPickerStackNavigator,
FlagCommentStackNavigator,
EditRequestStackNavigator,
+ SignInModalStackNavigator,
};
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js
index 088d1973570c..0f71853c3bd3 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js
@@ -109,6 +109,11 @@ function RigthModalNavigator() {
options={defaultModalScreenOptions}
component={ModalStackNavigators.EditRequestStackNavigator}
/>
+
);
}
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 4854d7ea96f4..eb0dca1a1713 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -341,6 +341,11 @@ export default {
EditRequest_Root: ROUTES.EDIT_REQUEST,
},
},
+ SignIn: {
+ screens: {
+ SignIn_Root: ROUTES.SIGNINMODAL,
+ },
+ },
},
},
},
diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js
index b1671cc46f7d..8a53d72d0a8b 100644
--- a/src/libs/actions/Session/index.js
+++ b/src/libs/actions/Session/index.js
@@ -90,11 +90,14 @@ function isAnonymousUser() {
}
function signOutAndRedirectToSignIn() {
- hideContextMenu(false);
- signOut();
- redirectToSignIn();
Log.info('Redirecting to Sign In because signOut() was called');
- if (isAnonymousUser()) {
+ hideContextMenu(false);
+ if (!isAnonymousUser()) {
+ signOut();
+ redirectToSignIn();
+ }
+ else {
+ Navigation.navigate(ROUTES.SIGNINMODAL);
Linking.getInitialURL().then((url) => {
const reportID = ReportUtils.getReportIDFromLink(url);
if (reportID) {
@@ -875,6 +878,87 @@ function validateTwoFactorAuth(twoFactorAuthCode) {
API.write('TwoFactorAuth_Validate', {twoFactorAuthCode}, {optimisticData, successData, failureData});
}
+function signInAnonymousAccount(validateCode, preferredLocale = CONST.LOCALES.DEFAULT) {
+ const optimisticData = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.ACCOUNT,
+ value: {
+ ...CONST.DEFAULT_ACCOUNT_DATA,
+ isLoading: true,
+ loadingForm: CONST.FORMS.VALIDATE_CODE_FORM,
+ },
+ },
+ {
+ // We need to clean the authToken so the app is refreshed
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.SESSION,
+ value: {
+ authToken: '',
+ },
+ },
+ ];
+
+ const successData = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.ACCOUNT,
+ value: {
+ isLoading: false,
+ loadingForm: null,
+ },
+ },
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.CREDENTIALS,
+ value: {
+ validateCode,
+ },
+ },
+ {
+ // We need to manually set the authTokenType to NOT be anonymous
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.SESSION,
+ value: {
+ authTokenType: '',
+ },
+ }
+ ];
+
+ const failureData = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.ACCOUNT,
+ value: {
+ isLoading: false,
+ loadingForm: null,
+ },
+ },
+ ];
+
+ const params = {
+ email: credentials.login,
+ preferredLocale,
+ validateCode: validateCode || credentials.validateCode,
+ };
+
+ // TODO: Switch to ClaimAnonymousAccount command, when backend is ready
+ Device.getDeviceInfoWithID().then((deviceInfo) => {
+ API.write(
+ 'SigninUser',
+ {
+ ...params,
+ deviceInfo,
+ },
+ {
+ optimisticData,
+ successData,
+ failureData,
+ },
+ );
+ });
+}
+
export {
beginSignIn,
checkIfActionIsAllowed,
@@ -902,4 +986,5 @@ export {
isAnonymousUser,
toggleTwoFactorAuth,
validateTwoFactorAuth,
+ signInAnonymousAccount,
};
diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js
index a500635222d6..f6a8b266032a 100644
--- a/src/libs/actions/SignInRedirect.js
+++ b/src/libs/actions/SignInRedirect.js
@@ -8,6 +8,7 @@ import NetworkConnection from '../NetworkConnection';
import HttpUtils from '../HttpUtils';
import navigationRef from '../Navigation/navigationRef';
import SCREENS from '../../SCREENS';
+import ROUTES from '../../ROUTES';
import Navigation from '../Navigation/Navigation';
import * as ErrorUtils from '../ErrorUtils';
diff --git a/src/pages/signin/SignInModal.js b/src/pages/signin/SignInModal.js
new file mode 100644
index 000000000000..694fc870cf9a
--- /dev/null
+++ b/src/pages/signin/SignInModal.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import SignInPage from './SignInPage';
+import ScreenWrapper from '../../components/ScreenWrapper';
+import HeaderWithBackButton from '../../components/HeaderWithBackButton';
+import Navigation from '../../libs/Navigation/Navigation';
+
+const propTypes = {
+};
+
+const defaultProps = {
+};
+
+function SignInModal(props) {
+ return (
+ {}}
+ >
+ Navigation.goBack()}
+ />
+
+
+
+ );
+}
+
+SignInModal.propTypes = propTypes;
+SignInModal.defaultProps = defaultProps;
+SignInModal.displayName = 'SignInModal';
+
+export default (SignInModal);
\ No newline at end of file
diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js
index a875c25359b0..68f1faae9a5e 100644
--- a/src/pages/signin/SignInPage.js
+++ b/src/pages/signin/SignInPage.js
@@ -47,6 +47,8 @@ const propTypes = {
twoFactorAuthCode: PropTypes.string,
}),
+ isInModal: PropTypes.bool,
+
...withLocalizePropTypes,
...windowDimensionsPropTypes,
@@ -56,6 +58,7 @@ const defaultProps = {
account: {},
betas: [],
credentials: {},
+ isInModal: false,
};
class SignInPage extends Component {
@@ -110,13 +113,13 @@ class SignInPage extends Component {
(!this.props.account.validated || this.props.account.forgotPassword) &&
!showUnlinkLoginForm &&
!Permissions.canUsePasswordlessLogins(this.props.betas);
-
+
let welcomeHeader = '';
let welcomeText = '';
if (showValidateCodeForm) {
if (this.props.account.requiresTwoFactorAuth) {
// We will only know this after a user signs in successfully, without their 2FA code
- welcomeHeader = this.props.isSmallScreenWidth ? '' : this.props.translate('welcomeText.welcomeBack');
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? '' : this.props.translate('welcomeText.welcomeBack');
welcomeText = this.props.translate('validateCodeForm.enterAuthenticatorCode');
} else {
const userLogin = Str.removeSMSDomain(lodashGet(this.props, 'credentials.login', ''));
@@ -124,27 +127,27 @@ class SignInPage extends Component {
// replacing spaces with "hard spaces" to prevent breaking the number
const userLoginToDisplay = Str.isSMSLogin(userLogin) ? this.props.formatPhoneNumber(userLogin).replace(/ /g, '\u00A0') : userLogin;
if (this.props.account.validated) {
- welcomeHeader = this.props.isSmallScreenWidth ? '' : this.props.translate('welcomeText.welcomeBack');
- welcomeText = this.props.isSmallScreenWidth
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? '' : this.props.translate('welcomeText.welcomeBack');
+ welcomeText = this.props.isSmallScreenWidth || this.props.isInModal
? `${this.props.translate('welcomeText.welcomeBack')} ${this.props.translate('welcomeText.welcomeEnterMagicCode', {login: userLoginToDisplay})}`
: this.props.translate('welcomeText.welcomeEnterMagicCode', {login: userLoginToDisplay});
} else {
- welcomeHeader = this.props.isSmallScreenWidth ? '' : this.props.translate('welcomeText.welcome');
- welcomeText = this.props.isSmallScreenWidth
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? '' : this.props.translate('welcomeText.welcome');
+ welcomeText = this.props.isSmallScreenWidth || this.props.isInModal
? `${this.props.translate('welcomeText.welcome')} ${this.props.translate('welcomeText.newFaceEnterMagicCode', {login: userLoginToDisplay})}`
: this.props.translate('welcomeText.newFaceEnterMagicCode', {login: userLoginToDisplay});
}
}
} else if (showPasswordForm) {
- welcomeHeader = this.props.isSmallScreenWidth ? '' : this.props.translate('welcomeText.welcomeBack');
- welcomeText = this.props.isSmallScreenWidth
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? '' : this.props.translate('welcomeText.welcomeBack');
+ welcomeText = this.props.isSmallScreenWidth || this.props.isInModal
? `${this.props.translate('welcomeText.welcomeBack')} ${this.props.translate('welcomeText.enterPassword')}`
: this.props.translate('welcomeText.enterPassword');
} else if (showUnlinkLoginForm) {
- welcomeHeader = this.props.isSmallScreenWidth ? this.props.translate('login.hero.header') : this.props.translate('welcomeText.welcomeBack');
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? this.props.translate('login.hero.header') : this.props.translate('welcomeText.welcomeBack');
} else if (!showResendValidationForm) {
- welcomeHeader = this.props.isSmallScreenWidth ? this.props.translate('login.hero.header') : this.props.translate('welcomeText.getStarted');
- welcomeText = this.props.isSmallScreenWidth ? this.props.translate('welcomeText.getStarted') : '';
+ welcomeHeader = this.props.isSmallScreenWidth || this.props.isInModal ? this.props.translate('login.hero.header') : this.props.translate('welcomeText.getStarted');
+ welcomeText = this.props.isSmallScreenWidth || this.props.isInModal ? this.props.translate('welcomeText.getStarted') : '';
}
return (
@@ -154,8 +157,9 @@ class SignInPage extends Component {
{/* LoginForm and PasswordForm must use the isVisible prop. This keeps them mounted, but visually hidden
so that password managers can access the values. Conditionally rendering these components will break this feature. */}
@@ -163,7 +167,7 @@ class SignInPage extends Component {
isVisible={showLoginForm}
blurOnSubmit={this.props.account.validated === false}
/>
- {showValidateCodeForm ? : }
+ {showValidateCodeForm ? : }
{showResendValidationForm && }
{showUnlinkLoginForm && }
diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js
index 954f8b2ebb8a..f4d9e2fab3ac 100644
--- a/src/pages/signin/SignInPageLayout/index.js
+++ b/src/pages/signin/SignInPageLayout/index.js
@@ -34,6 +34,8 @@ const propTypes = {
/** Whether to show welcome header on a particular page */
shouldShowWelcomeHeader: PropTypes.bool.isRequired,
+ isInModal: PropTypes.bool,
+
...windowDimensionsPropTypes,
};
@@ -45,7 +47,7 @@ function SignInPageLayout(props) {
// To scroll on both mobile and web, we need to set the container height manually
const containerHeight = props.windowHeight - props.insets.top - props.insets.bottom;
- if (props.isSmallScreenWidth) {
+ if (props.isSmallScreenWidth || props.isInModal) {
containerStyles = [styles.flex1];
contentContainerStyles = [styles.flex1, styles.flexColumn];
}
@@ -61,7 +63,7 @@ function SignInPageLayout(props) {
return (
- {!props.isSmallScreenWidth ? (
+ {!(props.isSmallScreenWidth || props.isInModal) ? (
);
}
diff --git a/src/pages/signin/ValidateCodeForm/index.js b/src/pages/signin/ValidateCodeForm/index.js
index e60c30bff359..853f9a475851 100644
--- a/src/pages/signin/ValidateCodeForm/index.js
+++ b/src/pages/signin/ValidateCodeForm/index.js
@@ -4,16 +4,19 @@ import BaseValidateCodeForm from './BaseValidateCodeForm';
const defaultProps = {
isVisible: false,
+ isInModal: false,
};
const propTypes = {
isVisible: PropTypes.bool,
+ isInModal: PropTypes.bool,
};
function ValidateCodeForm(props) {
return (
);
}