From e7bf8f784ba29c461cf4378f832916d16bec10b4 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Tue, 19 Oct 2021 08:12:43 +0530 Subject: [PATCH 1/4] Added Permission check --- .../Navigation/AppNavigator/AuthScreens.js | 28 +++++++++++-------- src/libs/actions/SignInRedirect.js | 4 ++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 8bd0c0658518..47fca2e77eb6 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -63,6 +63,7 @@ import defaultScreenOptions from './defaultScreenOptions'; import * as API from '../../API'; import {setLocale} from '../../actions/App'; import {cleanupSession} from '../../actions/Session'; +import Permissions from '../../Permissions'; Onyx.connect({ key: ONYXKEYS.MY_PERSONAL_DETAILS, @@ -142,17 +143,19 @@ class AuthScreens extends React.Component { NameValuePair.get(CONST.NVP.PRIORITY_MODE, ONYXKEYS.NVP_PRIORITY_MODE, 'default'); NameValuePair.get(CONST.NVP.IS_FIRST_TIME_NEW_EXPENSIFY_USER, ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, true); - API.Get({ - returnValueList: 'nameValuePairs', - nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, - }).then((response) => { - const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); - if ((currentPreferredLocale !== CONST.DEFAULT_LOCALE) && (preferredLocale !== currentPreferredLocale)) { - setLocale(currentPreferredLocale); - } else { - Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); - } - }); + if (Permissions.canUseInternationalization(this.props.betas)) { + API.Get({ + returnValueList: 'nameValuePairs', + nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, + }).then((response) => { + const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); + if ((currentPreferredLocale !== CONST.DEFAULT_LOCALE) && (preferredLocale !== currentPreferredLocale)) { + setLocale(currentPreferredLocale); + } else { + Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); + } + }); + } PersonalDetails.fetchPersonalDetails(); User.getUserDetails(); @@ -385,5 +388,8 @@ export default compose( network: { key: ONYXKEYS.NETWORK, }, + betas: { + key: ONYXKEYS.BETAS, + }, }), )(AuthScreens); diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index 95e8b862d8bc..a05faa8bdc8d 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -1,6 +1,7 @@ import Onyx from 'react-native-onyx'; import SignoutManager from '../SignoutManager'; import ONYXKEYS from '../../ONYXKEYS'; +import Permissions from '../Permissions'; let currentActiveClients; Onyx.connect({ @@ -26,7 +27,8 @@ function clearStorageAndRedirect(errorMessage) { // Clearing storage discards the authToken. This causes a redirect to the SignIn screen Onyx.clear() .then(() => { - if (preferredLocale) { + // Betas are only present when user is Logined + if (Permissions.canUseInternationalization([]) && preferredLocale) { Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); } if (activeClients && activeClients.length > 0) { From 783182de276a40f689c8825f0bdf4a0a652b0eb1 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 30 Oct 2021 06:29:35 +0530 Subject: [PATCH 2/4] race conditions resolved --- src/ONYXKEYS.js | 3 ++ .../Navigation/AppNavigator/AuthScreens.js | 28 ++++++---------- src/libs/actions/User.js | 33 ++++++++++++++++++- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index ece47440dabe..8715dd509aee 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -69,6 +69,9 @@ export default { SESSION: 'session', BETAS: 'betas', + // Set when we are loading payment methods + IS_LOADING_BETAS: 'isLoadingBetas', + // NVP keys // Contains the user's payPalMe address NVP_PAYPAL_ME_ADDRESS: 'nvp_paypalMeAddress', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index c63563492a21..69a80a7545c5 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -60,10 +60,7 @@ import SCREENS from '../../../SCREENS'; import Timers from '../../Timers'; import LogInWithShortLivedTokenPage from '../../../pages/LogInWithShortLivedTokenPage'; import defaultScreenOptions from './defaultScreenOptions'; -import * as API from '../../API'; -import {setLocale} from '../../actions/App'; import {cleanupSession} from '../../actions/Session'; -import Permissions from '../../Permissions'; Onyx.connect({ key: ONYXKEYS.MY_PERSONAL_DETAILS, @@ -117,6 +114,7 @@ const propTypes = { const defaultProps = { network: {isOffline: true}, + isLoadingBetas: true, }; class AuthScreens extends React.Component { @@ -142,21 +140,6 @@ class AuthScreens extends React.Component { // Fetch some data we need on initialization NameValuePair.get(CONST.NVP.PRIORITY_MODE, ONYXKEYS.NVP_PRIORITY_MODE, 'default'); NameValuePair.get(CONST.NVP.IS_FIRST_TIME_NEW_EXPENSIFY_USER, ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, true); - - if (Permissions.canUseInternationalization(this.props.betas)) { - API.Get({ - returnValueList: 'nameValuePairs', - nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, - }).then((response) => { - const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); - if ((currentPreferredLocale !== CONST.DEFAULT_LOCALE) && (preferredLocale !== currentPreferredLocale)) { - setLocale(currentPreferredLocale); - } else { - Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); - } - }); - } - PersonalDetails.fetchPersonalDetails(); User.getUserDetails(); User.getBetas(); @@ -219,6 +202,12 @@ class AuthScreens extends React.Component { return nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth; } + componentDidUpdate(prevProps) { + if (prevProps.isLoadingBetas && !this.props.isLoadingBetas) { + User.fetchAndSetPreferredLocale(this.props.betas, currentPreferredLocale); + } + } + componentWillUnmount() { if (this.unsubscribeSearchShortcut) { this.unsubscribeSearchShortcut(); @@ -392,5 +381,8 @@ export default compose( betas: { key: ONYXKEYS.BETAS, }, + isLoadingBetas: { + key: ONYXKEYS.IS_LOADING_BETAS, + }, }), )(AuthScreens); diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index 3021af64d784..2f312c94cd54 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -14,6 +14,9 @@ import Log from '../Log'; import NetworkConnection from '../NetworkConnection'; import NameValuePair from './NameValuePair'; import getSkinToneEmojiFromIndex from '../../pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex'; +import Permissions from '../Permissions'; +import {setLocale} from './App'; + let sessionAuthToken = ''; let sessionEmail = ''; @@ -58,9 +61,36 @@ function changePassword(oldPassword, password) { } function getBetas() { + Onyx.set(ONYXKEYS.IS_LOADING_BETAS, true); API.User_GetBetas().then((response) => { if (response.jsonCode === 200) { - Onyx.set(ONYXKEYS.BETAS, response.betas); + Onyx.multiSet({ + [ONYXKEYS.BETAS]: response.betas, + [ONYXKEYS.IS_LOADING_BETAS]: null, + }); + } + }); +} + +/** + * Fetches the User's preferred Locale and set the app locale if not same. + * + * @param {Array} betas + * @param {String} currentPreferredLocale + */ +function fetchAndSetPreferredLocale(betas, currentPreferredLocale) { + if (!Permissions.canUseInternationalization(betas)) { + return; + } + API.Get({ + returnValueList: 'nameValuePairs', + nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, + }).then((response) => { + const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); + if ((currentPreferredLocale !== CONST.DEFAULT_LOCALE) && (preferredLocale !== currentPreferredLocale)) { + setLocale(currentPreferredLocale); + } else { + Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); } }); } @@ -312,4 +342,5 @@ export { setPreferredSkinTone, setShouldUseSecureStaging, clearUserErrorMessage, + fetchAndSetPreferredLocale, }; From d8d4417ca191095ee47f654eea3cef311c502dc4 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 30 Oct 2021 07:20:39 +0530 Subject: [PATCH 3/4] allow render when betas are loaded in Authscreen --- src/libs/Navigation/AppNavigator/AuthScreens.js | 9 +++++++-- src/libs/actions/User.js | 10 +++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 69a80a7545c5..3dcbefa8d14c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -109,12 +109,17 @@ const propTypes = { isOffline: PropTypes.bool, }), + /** Beta features list */ + betas: PropTypes.arrayOf(PropTypes.string).isRequired, + + /** Whether betas are loading */ + isLoadingBetas: PropTypes.bool.isRequired, + ...windowDimensionsPropTypes, }; const defaultProps = { network: {isOffline: true}, - isLoadingBetas: true, }; class AuthScreens extends React.Component { @@ -199,7 +204,7 @@ class AuthScreens extends React.Component { } shouldComponentUpdate(nextProps) { - return nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth; + return nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth || nextProps.isLoadingBetas !== this.props.isLoadingBetas; } componentDidUpdate(prevProps) { diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index 2f312c94cd54..00197eb98a67 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -73,21 +73,21 @@ function getBetas() { } /** - * Fetches the User's preferred Locale and set the app locale if not same. + * Fetches the User's preferred Locale and set the app locale. * * @param {Array} betas * @param {String} currentPreferredLocale */ function fetchAndSetPreferredLocale(betas, currentPreferredLocale) { - if (!Permissions.canUseInternationalization(betas)) { - return; - } API.Get({ returnValueList: 'nameValuePairs', nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, }).then((response) => { const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); - if ((currentPreferredLocale !== CONST.DEFAULT_LOCALE) && (preferredLocale !== currentPreferredLocale)) { + if (currentPreferredLocale !== CONST.DEFAULT_LOCALE + && preferredLocale !== currentPreferredLocale + && Permissions.canUseInternationalization(betas) + ) { setLocale(currentPreferredLocale); } else { Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); From 8f9007ad7de34397e01722160a3fa409d34404e3 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sun, 31 Oct 2021 11:33:30 +0530 Subject: [PATCH 4/4] Refactor code to resolve race conditions --- src/ONYXKEYS.js | 3 -- src/components/withLocalize.js | 3 ++ .../Navigation/AppNavigator/AuthScreens.js | 31 +++---------------- src/libs/actions/User.js | 29 +++++++++-------- 4 files changed, 22 insertions(+), 44 deletions(-) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 8715dd509aee..ece47440dabe 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -69,9 +69,6 @@ export default { SESSION: 'session', BETAS: 'betas', - // Set when we are loading payment methods - IS_LOADING_BETAS: 'isLoadingBetas', - // NVP keys // Contains the user's payPalMe address NVP_PAYPAL_ME_ADDRESS: 'nvp_paypalMeAddress', diff --git a/src/components/withLocalize.js b/src/components/withLocalize.js index 0a6797ff027c..99c67e934a04 100755 --- a/src/components/withLocalize.js +++ b/src/components/withLocalize.js @@ -29,6 +29,9 @@ const withLocalizePropTypes = { /** Returns an internationally converted phone number with the country code */ fromLocalPhone: PropTypes.func.isRequired, + + /** The user's preferred locale e.g. 'en', 'es-ES' */ + preferredLocale: PropTypes.string.isRequired, }; const localeProviderPropTypes = { diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 3dcbefa8d14c..13cfc7544614 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -61,6 +61,7 @@ import Timers from '../../Timers'; import LogInWithShortLivedTokenPage from '../../../pages/LogInWithShortLivedTokenPage'; import defaultScreenOptions from './defaultScreenOptions'; import {cleanupSession} from '../../actions/Session'; +import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; Onyx.connect({ key: ONYXKEYS.MY_PERSONAL_DETAILS, @@ -81,12 +82,6 @@ Onyx.connect({ }, }); -let currentPreferredLocale; -Onyx.connect({ - key: ONYXKEYS.NVP_PREFERRED_LOCALE, - callback: val => currentPreferredLocale = val || CONST.DEFAULT_LOCALE, -}); - const RootStack = createCustomModalStackNavigator(); // We want to delay the re-rendering for components(e.g. ReportActionCompose) @@ -109,12 +104,7 @@ const propTypes = { isOffline: PropTypes.bool, }), - /** Beta features list */ - betas: PropTypes.arrayOf(PropTypes.string).isRequired, - - /** Whether betas are loading */ - isLoadingBetas: PropTypes.bool.isRequired, - + ...withLocalizePropTypes, ...windowDimensionsPropTypes, }; @@ -147,7 +137,7 @@ class AuthScreens extends React.Component { NameValuePair.get(CONST.NVP.IS_FIRST_TIME_NEW_EXPENSIFY_USER, ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, true); PersonalDetails.fetchPersonalDetails(); User.getUserDetails(); - User.getBetas(); + User.fetchBetasAndSetPreferredLocale(this.props.preferredLocale); User.getDomainInfo(); PersonalDetails.fetchLocalCurrency(); fetchAllReports(true, true); @@ -204,13 +194,7 @@ class AuthScreens extends React.Component { } shouldComponentUpdate(nextProps) { - return nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth || nextProps.isLoadingBetas !== this.props.isLoadingBetas; - } - - componentDidUpdate(prevProps) { - if (prevProps.isLoadingBetas && !this.props.isLoadingBetas) { - User.fetchAndSetPreferredLocale(this.props.betas, currentPreferredLocale); - } + return nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth; } componentWillUnmount() { @@ -379,15 +363,10 @@ AuthScreens.propTypes = propTypes; AuthScreens.defaultProps = defaultProps; export default compose( withWindowDimensions, + withLocalize, withOnyx({ network: { key: ONYXKEYS.NETWORK, }, - betas: { - key: ONYXKEYS.BETAS, - }, - isLoadingBetas: { - key: ONYXKEYS.IS_LOADING_BETAS, - }, }), )(AuthScreens); diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index 00197eb98a67..c9714f93baee 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -61,28 +61,27 @@ function changePassword(oldPassword, password) { } function getBetas() { - Onyx.set(ONYXKEYS.IS_LOADING_BETAS, true); - API.User_GetBetas().then((response) => { + return API.User_GetBetas().then((response) => { if (response.jsonCode === 200) { - Onyx.multiSet({ - [ONYXKEYS.BETAS]: response.betas, - [ONYXKEYS.IS_LOADING_BETAS]: null, - }); + Onyx.set(ONYXKEYS.BETAS, response.betas); + return response.betas; } + return []; }); } /** - * Fetches the User's preferred Locale and set the app locale. - * - * @param {Array} betas + * Fetches betas and User's preferred Locale, then set the app locale. * @param {String} currentPreferredLocale */ -function fetchAndSetPreferredLocale(betas, currentPreferredLocale) { - API.Get({ - returnValueList: 'nameValuePairs', - nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, - }).then((response) => { +function fetchBetasAndSetPreferredLocale(currentPreferredLocale) { + Promise.all([ + getBetas(), + API.Get({ + returnValueList: 'nameValuePairs', + nvpNames: ONYXKEYS.NVP_PREFERRED_LOCALE, + }), + ]).then((betas, response) => { const preferredLocale = lodashGet(response, ['nameValuePairs', 'preferredLocale'], CONST.DEFAULT_LOCALE); if (currentPreferredLocale !== CONST.DEFAULT_LOCALE && preferredLocale !== currentPreferredLocale @@ -342,5 +341,5 @@ export { setPreferredSkinTone, setShouldUseSecureStaging, clearUserErrorMessage, - fetchAndSetPreferredLocale, + fetchBetasAndSetPreferredLocale, };