From 51f9f7444136ab4e19d6b35587357475b0702160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Tue, 26 Sep 2023 16:31:51 +0200 Subject: [PATCH 1/5] fix --- src/libs/Navigation/Navigation.js | 46 +++++++++++++++++++++++++++++++ src/libs/actions/Report.js | 18 +++++++----- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index dc4f35a59cba..765332d4ea03 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -255,6 +255,51 @@ function setIsNavigationReady() { resolveNavigationIsReadyPromise(); } +function navContainsConcierge(state) { + if (!state || !state.routeNames || !_.isArray(state.routeNames)) { + return false; + } + + return _.includes(state.routeNames, SCREENS.CONCIERGE); +} + +/** + * Waits for the navigation state to contain protected routes (specifically 'Concierge'). + * If the navigation is in a state, where protected routes are available, the promise will resolve immediately. + * + * @function + * @returns {Promise} A promise that resolves to `true` when the Concierge route is present. + * Rejects with an error if the navigation is not ready. + * + * @example + * waitForProtectedRoutes() + * .then(() => console.log('Protected routes are present!')) + * .catch(error => console.error(error.message)); + */ +function waitForProtectedRoutes() { + return new Promise((resolve, reject) => { + const isReady = navigationRef.current && navigationRef.current.isReady(); + if (!isReady) { + reject(new Error('[Navigation] is not ready yet!')); + return; + } + const currentState = navigationRef.current.getState(); + if (navContainsConcierge(currentState)) { + resolve(); + return; + } + let unsubscribe; + const handleStateChange = ({data}) => { + const state = lodashGet(data, 'state'); + if (navContainsConcierge(state)) { + unsubscribe(); + resolve(); + } + }; + unsubscribe = navigationRef.current.addListener('state', handleStateChange); + }); +} + export default { setShouldPopAllStateOnUP, canNavigate, @@ -268,6 +313,7 @@ export default { setIsNavigationReady, getTopmostReportId, getRouteNameFromStateEvent, + waitForProtectedRoutes, }; export {navigationRef}; diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 296abc6a9cfa..eb06e76b14db 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -8,7 +8,7 @@ import moment from 'moment'; import ONYXKEYS from '../../ONYXKEYS'; import * as Pusher from '../Pusher/pusher'; import LocalNotification from '../Notification/LocalNotification'; -import Navigation from '../Navigation/Navigation'; +import Navigation, {navigationRef} from '../Navigation/Navigation'; import * as ActiveClientManager from '../ActiveClientManager'; import Visibility from '../Visibility'; import ROUTES from '../../ROUTES'; @@ -1807,7 +1807,6 @@ function toggleEmojiReaction(reportID, reportAction, reactionObject, existingRea * @param {Boolean} isAuthenticated */ function openReportFromDeepLink(url, isAuthenticated) { - const route = ReportUtils.getRouteFromLink(url); const reportID = ReportUtils.getReportIDFromLink(url); if (reportID && !isAuthenticated) { @@ -1826,11 +1825,16 @@ function openReportFromDeepLink(url, isAuthenticated) { // Navigate to the report after sign-in/sign-up. InteractionManager.runAfterInteractions(() => { Session.waitForUserSignIn().then(() => { - if (route === ROUTES.CONCIERGE) { - navigateToConciergeChat(); - return; - } - Navigation.navigate(route, CONST.NAVIGATION.TYPE.PUSH); + Navigation.waitForProtectedRoutes() + .then(() => { + const route = ReportUtils.getRouteFromLink(url); + if (route === ROUTES.CONCIERGE) { + navigateToConciergeChat(); + return; + } + Navigation.navigate(route, CONST.NAVIGATION.TYPE.PUSH); + }) + .catch((error) => Log.warn(error.message)); }); }); } From e9330ea1e40061ddcbd1db3b18fb66ac4fa1054f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Wed, 27 Sep 2023 10:30:40 +0200 Subject: [PATCH 2/5] linting --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index eb06e76b14db..d91117bb908b 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -8,7 +8,7 @@ import moment from 'moment'; import ONYXKEYS from '../../ONYXKEYS'; import * as Pusher from '../Pusher/pusher'; import LocalNotification from '../Notification/LocalNotification'; -import Navigation, {navigationRef} from '../Navigation/Navigation'; +import Navigation from '../Navigation/Navigation'; import * as ActiveClientManager from '../ActiveClientManager'; import Visibility from '../Visibility'; import ROUTES from '../../ROUTES'; From 958b028793250d214cc2b2d329af3d163173c921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Tue, 10 Oct 2023 11:33:38 +0200 Subject: [PATCH 3/5] checking for multiple protected screens --- src/SCREENS.ts | 15 ++++++++++----- src/libs/Navigation/Navigation.js | 20 +++++++++++++++----- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index eb125a43c239..e46a6ce5c9e9 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -2,15 +2,18 @@ * This is a file containing constants for all of the screen names. In most cases, we should use the routes for * navigation. But there are situations where we may need to access screen names directly. */ -export default { + +export const PROTECTED_SCREENS = { HOME: 'Home', + CONCIERGE: 'Concierge', + REPORT_ATTACHMENTS: 'ReportAttachments', +} as const; + +export default { + ...PROTECTED_SCREENS, LOADING: 'Loading', REPORT: 'Report', - REPORT_ATTACHMENTS: 'ReportAttachments', NOT_FOUND: 'not-found', - TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', - VALIDATE_LOGIN: 'ValidateLogin', - CONCIERGE: 'Concierge', SETTINGS: { ROOT: 'Settings_Root', PREFERENCES: 'Settings_Preferences', @@ -21,7 +24,9 @@ export default { SAVE_THE_WORLD: { ROOT: 'SaveTheWorld_Root', }, + TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', DESKTOP_SIGN_IN_REDIRECT: 'DesktopSignInRedirect', + VALIDATE_LOGIN: 'ValidateLogin', } as const; diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index 4a067f9523cf..56993e19b683 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -12,7 +12,7 @@ import NAVIGATORS from '../../NAVIGATORS'; import originalGetTopmostReportId from './getTopmostReportId'; import originalGetTopmostReportActionId from './getTopmostReportActionID'; import getStateFromPath from './getStateFromPath'; -import SCREENS from '../../SCREENS'; +import SCREENS, {PROTECTED_SCREENS} from '../../SCREENS'; import CONST from '../../CONST'; let resolveNavigationIsReadyPromise; @@ -259,12 +259,22 @@ function setIsNavigationReady() { resolveNavigationIsReadyPromise(); } -function navContainsConcierge(state) { +/** + * Checks if the navigation state contains routes that are protected (over the auth wall). + * + * @function + * @param {Object} state - react-navigation state object + * + * @returns {Boolean} + */ +function navContainsProtectedRoutes(state) { if (!state || !state.routeNames || !_.isArray(state.routeNames)) { return false; } + const protectedScreensNames = _.values(PROTECTED_SCREENS); + const difference = _.difference(protectedScreensNames, state.routeNames); - return _.includes(state.routeNames, SCREENS.CONCIERGE); + return !difference.length; } /** @@ -288,14 +298,14 @@ function waitForProtectedRoutes() { return; } const currentState = navigationRef.current.getState(); - if (navContainsConcierge(currentState)) { + if (navContainsProtectedRoutes(currentState)) { resolve(); return; } let unsubscribe; const handleStateChange = ({data}) => { const state = lodashGet(data, 'state'); - if (navContainsConcierge(state)) { + if (navContainsProtectedRoutes(state)) { unsubscribe(); resolve(); } From f2d683f71222a070e139bd5c842b00bf52a1fd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Tue, 10 Oct 2023 12:22:07 +0200 Subject: [PATCH 4/5] linting --- src/SCREENS.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index ed7459e245e4..7df37045b959 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -2,8 +2,7 @@ * This is a file containing constants for all of the screen names. In most cases, we should use the routes for * navigation. But there are situations where we may need to access screen names directly. */ - -export const PROTECTED_SCREENS = { +const PROTECTED_SCREENS = { HOME: 'Home', CONCIERGE: 'Concierge', REPORT_ATTACHMENTS: 'ReportAttachments', @@ -43,3 +42,5 @@ export default { GROUPS_WORKSPACES_OLDDOT: 'GroupWorkspaces_OLDDOT', CARDS_AND_DOMAINS_OLDDOT: 'CardsAndDomains_OLDDOT', } as const; + +export {PROTECTED_SCREENS}; From 6d499eb3a4515a42ef5ede72a0824da7843620fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Wed, 11 Oct 2023 16:30:07 +0200 Subject: [PATCH 5/5] comment fix --- src/libs/Navigation/Navigation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index 9ad9347e136d..0994e491ae2d 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -282,7 +282,7 @@ function navContainsProtectedRoutes(state) { } /** - * Waits for the navigation state to contain protected routes (specifically 'Concierge'). + * Waits for the navigation state to contain protected routes specified in PROTECTED_SCREENS constant * If the navigation is in a state, where protected routes are available, the promise will resolve immediately. * * @function