From 3edeb909a7a629c8b2608c6be2fa8e49b8714e40 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 30 Apr 2021 17:31:12 +0300 Subject: [PATCH 1/2] fix: Incomplete reports would cause the app to crash on start up Added filtering so that only valid reports are processed by findLastAccessedReport Updated getInitialReport to getInitialReportScreenParams and moved to utils --- .../AppNavigator/MainDrawerNavigator.js | 9 ++------ src/libs/reportUtils.js | 21 ++++++++++++++++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js index 7dd353a5927e2..f1206e91ac232 100644 --- a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js +++ b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js @@ -6,7 +6,7 @@ import {withOnyx} from 'react-native-onyx'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import FullScreenLoadingIndicator from '../../../components/FullscreenLoadingIndicator'; -import {getLastAccessedReport} from '../../reportUtils'; +import {getInitialReportScreenParams} from '../../reportUtils'; import styles, { getNavigationDrawerType, getNavigationDrawerStyle, @@ -34,17 +34,12 @@ const defaultProps = { const Drawer = createDrawerNavigator(); -// Decorated to always returning the result of the first call - keeps Screen initialParams from changing -const getInitialReport = _.once(getLastAccessedReport); - const MainDrawerNavigator = (props) => { // When there are no reports there's no point to render the empty navigator if (_.size(props.reports) === 0) { return ; } - const initialReportID = getInitialReport(props.reports).reportID; - /* After the app initializes and reports are available the home navigation is mounted * This way routing information is updated (if needed) based on the initial report ID resolved. * This is usually needed after login/create account and re-launches */ @@ -67,7 +62,7 @@ const MainDrawerNavigator = (props) => { ); diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 668aca5c41b77..b7aad86b563a3 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -1,5 +1,6 @@ import _ from 'underscore'; import Str from 'expensify-common/lib/str'; +import lodashGet from 'lodash/get'; /** * Returns the concatenated title for the PrimaryLogins of a report @@ -24,19 +25,33 @@ function isReportMessageAttachment(reportMessageText) { /** * Given a collection of reports returns the most recently accessed one * - * @param {Record|Array<{lastVisitedTimestamp}>} reports + * @param {Record|Array<{lastVisitedTimestamp, reportID}>} reports * @returns {Object} */ -function getLastAccessedReport(reports) { +function findLastAccessedReport(reports) { return _.chain(reports) .toArray() + .filter(report => report && report.reportID) .sortBy('lastVisitedTimestamp') .last() .value(); } +/** + * We are decorating findLastAccessedReport so that it caches the first result once the reports load. + * This will ensure the initialParams are only set once for the ReportScreen. + */ +const getInitialReportScreenParams = _.once((reports) => { + const last = findLastAccessedReport(reports); + + // Fallback to empty if for some reason reportID cannot be derived - prevents the app from crashing + const reportID = lodashGet(last, 'reportID', ''); + return {reportID}; +}); + export { getReportParticipantsTitle, isReportMessageAttachment, - getLastAccessedReport, + findLastAccessedReport, + getInitialReportScreenParams, }; From bc63c492e068d8b2a1c3361579e13d5894f3ca8b Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 30 Apr 2021 20:21:03 +0300 Subject: [PATCH 2/2] refactor: move `getInitialReportScreenParams` to `MainDrawerNavigator` --- .../AppNavigator/MainDrawerNavigator.js | 21 ++++++++++++++----- src/libs/reportUtils.js | 14 ------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js index f1206e91ac232..f53b61989864b 100644 --- a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js +++ b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js @@ -1,16 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import _ from 'underscore'; +import lodashGet from 'lodash/get'; import {createDrawerNavigator} from '@react-navigation/drawer'; import {withOnyx} from 'react-native-onyx'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import FullScreenLoadingIndicator from '../../../components/FullscreenLoadingIndicator'; -import {getInitialReportScreenParams} from '../../reportUtils'; -import styles, { - getNavigationDrawerType, - getNavigationDrawerStyle, -} from '../../../styles/styles'; +import styles, {getNavigationDrawerStyle, getNavigationDrawerType} from '../../../styles/styles'; import ONYXKEYS from '../../../ONYXKEYS'; import compose from '../../compose'; import SCREENS from '../../../SCREENS'; @@ -18,6 +15,7 @@ import SCREENS from '../../../SCREENS'; // Screens import SidebarScreen from '../../../pages/home/sidebar/SidebarScreen'; import ReportScreen from '../../../pages/home/ReportScreen'; +import {findLastAccessedReport} from '../../reportUtils'; const propTypes = { // Available reports that would be displayed in this navigator @@ -34,6 +32,18 @@ const defaultProps = { const Drawer = createDrawerNavigator(); +/** + * We are decorating findLastAccessedReport so that it caches the first result once the reports load. + * This will ensure the initialParams are only set once for the ReportScreen. + */ +const getInitialReportScreenParams = _.once((reports) => { + const last = findLastAccessedReport(reports); + + // Fallback to empty if for some reason reportID cannot be derived - prevents the app from crashing + const reportID = lodashGet(last, 'reportID', ''); + return {reportID}; +}); + const MainDrawerNavigator = (props) => { // When there are no reports there's no point to render the empty navigator if (_.size(props.reports) === 0) { @@ -80,3 +90,4 @@ export default compose( }, }), )(MainDrawerNavigator); +export {getInitialReportScreenParams}; diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index b7aad86b563a3..b46e3acfe60b4 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -1,6 +1,5 @@ import _ from 'underscore'; import Str from 'expensify-common/lib/str'; -import lodashGet from 'lodash/get'; /** * Returns the concatenated title for the PrimaryLogins of a report @@ -37,21 +36,8 @@ function findLastAccessedReport(reports) { .value(); } -/** - * We are decorating findLastAccessedReport so that it caches the first result once the reports load. - * This will ensure the initialParams are only set once for the ReportScreen. - */ -const getInitialReportScreenParams = _.once((reports) => { - const last = findLastAccessedReport(reports); - - // Fallback to empty if for some reason reportID cannot be derived - prevents the app from crashing - const reportID = lodashGet(last, 'reportID', ''); - return {reportID}; -}); - export { getReportParticipantsTitle, isReportMessageAttachment, findLastAccessedReport, - getInitialReportScreenParams, };