Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay report history fetch to give app a chance to initialize #2519

Merged
merged 3 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import CONST from '../../../CONST';
import compose from '../../compose';
import {
subscribeToReportCommentEvents,
fetchAll as fetchAllReports,
fetchAllReports,
} from '../../actions/Report';
import * as PersonalDetails from '../../actions/PersonalDetails';
import * as Pusher from '../../Pusher/pusher';
Expand Down Expand Up @@ -119,7 +119,7 @@ class AuthScreens extends React.Component {
PersonalDetails.fetch();
User.getUserDetails();
User.getBetas();
fetchAllReports(true, true);
fetchAllReports(true, true, true);
fetchCountryCodeByRequestIP();
UnreadIndicatorUpdater.listenForReportChanges();

Expand Down
99 changes: 51 additions & 48 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ function updateIOUReportData(chatReport) {
* chat report IDs
*
* @param {Array} chatList
* @return {Promise} only used internally when fetchAll() is called
* @return {Promise} only used internally when fetchAllReports() is called
*/
function fetchChatReportsByIDs(chatList) {
let fetchedReports;
Expand Down Expand Up @@ -315,7 +315,6 @@ function fetchChatReportsByIDs(chatList) {
// than updating props for each report and re-rendering had merge been used.
Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT_IOUS, reportIOUData);
Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, simplifiedReports);
Onyx.set(ONYXKEYS.INITIAL_REPORT_DATA_LOADED, true);

// Fetch the personal details if there are any
PersonalDetails.getFromReportParticipants(Object.values(simplifiedReports));
Expand Down Expand Up @@ -580,13 +579,14 @@ function unsubscribeFromReportChannel(reportID) {
* set of participants and redirect to it.
*
* @param {String[]} participants
* @returns {Promise}
*/
function fetchOrCreateChatReport(participants) {
if (participants.length < 2) {
throw new Error('fetchOrCreateChatReport() must have at least two participants');
}

API.CreateChatReport({
return API.CreateChatReport({
emailList: participants.join(','),
})
.then((data) => {
Expand All @@ -603,33 +603,6 @@ function fetchOrCreateChatReport(participants) {
});
}

/**
* Get all chat reports and provide the proper report name
* by fetching sharedReportList and personalDetails
*
* @returns {Promise} only used internally when fetchAll() is called
*/
function fetchChatReports() {
return API.Get({
returnValueList: 'chatList',
})
.then((response) => {
if (response.jsonCode !== 200) {
return;
}

// Get all the chat reports if they have any, otherwise create one with concierge
if (lodashGet(response, 'chatList', []).length) {
// The string cast here is necessary as Get rvl='chatList' may return an int
fetchChatReportsByIDs(String(response.chatList).split(','));
} else {
fetchOrCreateChatReport([currentUserEmail, '[email protected]']);
}

return response.chatList;
});
}

/**
* Get the actions of a report
*
Expand Down Expand Up @@ -674,30 +647,60 @@ function fetchActions(reportID, offset) {
*
* @param {Boolean} shouldRedirectToReport this is set to false when the network reconnect code runs
* @param {Boolean} shouldRecordHomePageTiming whether or not performance timing should be measured
* @param {Boolean} shouldDelayActionsFetch when the app loads we want to delay the fetching of additional actions
*/
function fetchAll(shouldRedirectToReport = true, shouldRecordHomePageTiming = false) {
fetchChatReports()
.then((reportIDs) => {
if (shouldRedirectToReport) {
// Update currentlyViewedReportID to be our first reportID from our report collection if we don't have
// one already.
if (lastViewedReportID) {
return;
}
function fetchAllReports(
shouldRedirectToReport = true,
shouldRecordHomePageTiming = false,
shouldDelayActionsFetch = false,
) {
let reportIDs = [];

API.Get({
returnValueList: 'chatList',
})
.then((response) => {
if (response.jsonCode !== 200) {
return;
}

const firstReportID = _.first(reportIDs);
const currentReportID = firstReportID ? String(firstReportID) : '';
Onyx.merge(ONYXKEYS.CURRENTLY_VIEWED_REPORTID, currentReportID);
// The string cast here is necessary as Get rvl='chatList' may return an int
reportIDs = String(response.chatList).split(',');

// Get all the chat reports if they have any, otherwise create one with concierge
if (reportIDs.length) {
return fetchChatReportsByIDs(reportIDs);
}

Log.info('[Report] Fetching report actions for reports', true, {reportIDs});
_.each(reportIDs, (reportID) => {
fetchActions(reportID);
});
return fetchOrCreateChatReport([currentUserEmail, '[email protected]']);
})
.then(() => {
Onyx.set(ONYXKEYS.INITIAL_REPORT_DATA_LOADED, true);

if (shouldRecordHomePageTiming) {
Timing.end(CONST.TIMING.HOMEPAGE_REPORTS_LOADED);
}

// Optionally delay fetching report history as it significantly increases sign in to interactive time
_.delay(() => {
Log.info('[Report] Fetching report actions for reports', true, {reportIDs});
_.each(reportIDs, (reportID) => {
fetchActions(reportID);
});

// We are waiting 8 seconds since this provides a good time window to allow the UI to finish loading before
// bogging it down with more requests and operations.
}, shouldDelayActionsFetch ? 8000 : 0);

// Update currentlyViewedReportID to be our first reportID from our report collection if we don't have
// one already.
if (!shouldRedirectToReport || lastViewedReportID) {
return;
}

const firstReportID = _.first(reportIDs);
const currentReportID = firstReportID ? String(firstReportID) : '';
Onyx.merge(ONYXKEYS.CURRENTLY_VIEWED_REPORTID, currentReportID);
});
}

Expand Down Expand Up @@ -894,11 +897,11 @@ Onyx.connect({

// When the app reconnects from being offline, fetch all of the reports and their actions
NetworkConnection.onReconnect(() => {
fetchAll(false);
fetchAllReports(false);
});

export {
fetchAll,
fetchAllReports,
fetchActions,
fetchOrCreateChatReport,
addAction,
Expand Down
7 changes: 6 additions & 1 deletion src/pages/home/report/ReportActionItemSingle.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const propTypes = {
action: PropTypes.shape(ReportActionPropTypes).isRequired,

// All of the personalDetails
personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired,
personalDetails: PropTypes.objectOf(personalDetailsPropType),
};

const defaultProps = {
personalDetails: {},
};

const ReportActionItemSingle = ({action, personalDetails}) => {
Expand Down Expand Up @@ -59,6 +63,7 @@ const ReportActionItemSingle = ({action, personalDetails}) => {
};

ReportActionItemSingle.propTypes = propTypes;
ReportActionItemSingle.defaultProps = defaultProps;
export default withOnyx({
personalDetails: {
key: ONYXKEYS.PERSONAL_DETAILS,
Expand Down
12 changes: 12 additions & 0 deletions src/pages/home/sidebar/SidebarLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ const propTypes = {

// The chat priority mode
priorityMode: PropTypes.string,

// Whether we have the necessary report data to load the sidebar
initialReportDataLoaded: PropTypes.bool,
};

const defaultProps = {
Expand All @@ -80,6 +83,7 @@ const defaultProps = {
network: null,
currentlyViewedReportID: '',
priorityMode: CONST.PRIORITY_MODE.DEFAULT,
initialReportDataLoaded: false,
};

class SidebarLinks extends React.Component {
Expand All @@ -88,6 +92,11 @@ class SidebarLinks extends React.Component {
}

render() {
// Wait until the reports are actually loaded before displaying the LHN
if (!this.props.initialReportDataLoaded) {
return null;
}

const activeReportID = parseInt(this.props.currentlyViewedReportID, 10);

const {recentReports} = getSidebarOptions(
Expand Down Expand Up @@ -184,5 +193,8 @@ export default compose(
priorityMode: {
key: ONYXKEYS.NVP_PRIORITY_MODE,
},
initialReportDataLoaded: {
key: ONYXKEYS.INITIAL_REPORT_DATA_LOADED,
},
}),
)(SidebarLinks);