Skip to content
6 changes: 3 additions & 3 deletions src/Expensify.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, {PureComponent} from 'react';
import {AppState, Linking} from 'react-native';
import Onyx, {withOnyx} from 'react-native-onyx';

import * as ReportUtils from './libs/ReportUtils';
import * as Report from './libs/actions/Report';
import BootSplash from './libs/BootSplash';
import * as ActiveClientManager from './libs/ActiveClientManager';
import ONYXKEYS from './ONYXKEYS';
Expand Down Expand Up @@ -124,7 +124,7 @@ class Expensify extends PureComponent {
this.appStateChangeListener = AppState.addEventListener('change', this.initializeClient);

// Open chat report from a deep link (only mobile native)
Linking.addEventListener('url', state => ReportUtils.openReportFromDeepLink(state.url));
Linking.addEventListener('url', state => Report.openReportFromDeepLink(state.url));
}

componentDidUpdate() {
Expand All @@ -141,7 +141,7 @@ class Expensify extends PureComponent {
this.setState({isSplashShown: false});

// If the app is opened from a deep link, get the reportID (if exists) from the deep link and navigate to the chat report
Linking.getInitialURL().then(url => ReportUtils.openReportFromDeepLink(url));
Linking.getInitialURL().then(url => Report.openReportFromDeepLink(url));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default {
*/
parseReportRouteParams: (route) => {
if (!route.startsWith(Url.addTrailingForwardSlash(REPORT))) {
return {};
return {reportID: '', isSubReportPageRoute: false};
}

const pathSegments = route.split('/');
Expand Down
9 changes: 8 additions & 1 deletion src/libs/Navigation/Navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let drawerIsReadyPromise = new Promise((resolve) => {
});

let resolveReportScreenIsReadyPromise;
const reportScreenIsReadyPromise = new Promise((resolve) => {
let reportScreenIsReadyPromise = new Promise((resolve) => {
resolveReportScreenIsReadyPromise = resolve;
});

Expand Down Expand Up @@ -268,6 +268,12 @@ function setIsNavigationReady() {
resolveNavigationIsReadyPromise();
}

function resetIsReportScreenReadyPromise() {
reportScreenIsReadyPromise = new Promise((resolve) => {
resolveReportScreenIsReadyPromise = resolve;
});
}

/**
* @returns {Promise}
*/
Expand Down Expand Up @@ -309,6 +315,7 @@ export default {
isDrawerReady,
setIsDrawerReady,
resetDrawerIsReadyPromise,
resetIsReportScreenReadyPromise,
isDrawerRoute,
setIsNavigating,
isReportScreenReady,
Expand Down
31 changes: 12 additions & 19 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import lodashGet from 'lodash/get';
import lodashIntersection from 'lodash/intersection';
import Onyx from 'react-native-onyx';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import {InteractionManager} from 'react-native';
import ONYXKEYS from '../ONYXKEYS';
import CONST from '../CONST';
import * as Localize from './Localize';
Expand Down Expand Up @@ -1539,7 +1538,7 @@ function getCommentLength(textComment) {
* @param {String|null} url
* @returns {String}
*/
function getReportIDFromDeepLink(url) {
function getRouteFromLink(url) {
if (!url) {
return '';
}
Expand All @@ -1566,27 +1565,21 @@ function getReportIDFromDeepLink(url) {
route = route.replace('/', '');
}
});
const {reportID, isSubReportPageRoute} = ROUTES.parseReportRouteParams(route);
if (isSubReportPageRoute) {
// We allow the Sub-Report deep link routes (settings, details, etc.) to be handled by their respective component pages
return '';
}
return reportID;
return route;
}

/**
* @param {String|null} url
* @returns {String}
*/
function openReportFromDeepLink(url) {
const reportID = getReportIDFromDeepLink(url);
if (!reportID) {
return;
function getReportIDFromLink(url) {
const route = getRouteFromLink(url);
const {reportID, isSubReportPageRoute} = ROUTES.parseReportRouteParams(route);
if (isSubReportPageRoute) {
// We allow the Sub-Report deep link routes (settings, details, etc.) to be handled by their respective component pages
return '';
}
InteractionManager.runAfterInteractions(() => {
Navigation.isReportScreenReady().then(() => {
Navigation.navigate(ROUTES.getReportRoute(reportID));
});
});
return reportID;
}

/**
Expand Down Expand Up @@ -1683,7 +1676,8 @@ export {
getRoomWelcomeMessage,
getDisplayNamesWithTooltips,
getReportName,
getReportIDFromDeepLink,
getReportIDFromLink,
getRouteFromLink,
navigateToDetailsPage,
generateReportID,
hasReportNameError,
Expand All @@ -1710,7 +1704,6 @@ export {
hashLogin,
getDefaultWorkspaceAvatar,
getCommentLength,
openReportFromDeepLink,
getFullSizeAvatar,
getSmallSizeAvatar,
getIOUOptions,
Expand Down
21 changes: 20 additions & 1 deletion src/libs/actions/Report.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Linking} from 'react-native';
import {Linking, InteractionManager} from 'react-native';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
Expand Down Expand Up @@ -1367,6 +1367,24 @@ function toggleEmojiReaction(reportID, reportAction, emoji, paramSkinTone = pref
return addEmojiReaction(reportID, reportAction, emoji, skinTone);
}

/**
* @param {String|null} url
*/
function openReportFromDeepLink(url) {
InteractionManager.runAfterInteractions(() => {
Navigation.isReportScreenReady().then(() => {
const route = ReportUtils.getRouteFromLink(url);
const reportID = ReportUtils.getReportIDFromLink(url);
if (reportID) {
Navigation.navigate(ROUTES.getReportRoute(reportID));
}
if (route === ROUTES.CONCIERGE) {
navigateToConciergeChat();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from #27042.

Another bug occurs due to this change. When a user logs out and then deep links to the /concierge using a different account, the previous user's concierge report is opened. This happens because we store the concierge reportID in a local variable in Report.js, more context in #27042 (comment)

}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✋ Coming from #23745

We are not handling the navigation from other URLs except the report or concierge here.

});
});
}

function getCurrentUserAccountID() {
return currentUserAccountID;
}
Expand Down Expand Up @@ -1395,6 +1413,7 @@ export {
readNewestAction,
readOldestAction,
openReport,
openReportFromDeepLink,
navigateToAndOpenReport,
openPaymentDetailsPage,
updatePolicyRoomName,
Expand Down
4 changes: 4 additions & 0 deletions src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class ReportScreen extends React.Component {
toggleReportActionComposeView(true);
}

componentWillUnmount() {
Navigation.resetIsReportScreenReadyPromise();
}

/**
* @param {String} text
*/
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/ReportUtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,21 @@ describe('ReportUtils', () => {
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.SEND)).toBe(true);
});
});

describe('getReportIDFromLink', () => {
it('should get the correct reportID from a deep link', () => {
expect(ReportUtils.getReportIDFromLink('new-expensify://r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('https://www.expensify.cash/r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('https://staging.new.expensify.com/r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('http://localhost/r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('http://localhost:8080/r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('https://staging.expensify.cash/r/75431276')).toBe('75431276');
expect(ReportUtils.getReportIDFromLink('https://new.expensify.com/r/75431276')).toBe('75431276');
});

it('shouldn\'t get the correct reportID from a deep link', () => {
expect(ReportUtils.getReportIDFromLink('new-expensify-not-valid://r/75431276')).toBe('');
expect(ReportUtils.getReportIDFromLink('new-expensify://settings')).toBe('');
});
});
});