diff --git a/src/pages/LoadingPage.js b/src/pages/LoadingPage.js new file mode 100644 index 000000000000..fc315495619a --- /dev/null +++ b/src/pages/LoadingPage.js @@ -0,0 +1,36 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useThemeStyles from '@hooks/useThemeStyles'; + +const propTypes = { + /** Method to trigger when pressing back button of the header */ + onBackButtonPress: PropTypes.func, + title: PropTypes.string.isRequired, +}; + +const defaultProps = { + onBackButtonPress: undefined, +}; + +function LoadingPage(props) { + const styles = useThemeStyles(); + return ( + + + + + ); +} + +LoadingPage.displayName = 'LoadingPage'; +LoadingPage.propTypes = propTypes; +LoadingPage.defaultProps = defaultProps; + +export default LoadingPage; diff --git a/src/pages/PrivateNotes/PrivateNotesEditPage.js b/src/pages/PrivateNotes/PrivateNotesEditPage.js index c62fbe3edcb5..0d4bc2c3e7e1 100644 --- a/src/pages/PrivateNotes/PrivateNotesEditPage.js +++ b/src/pages/PrivateNotes/PrivateNotesEditPage.js @@ -182,7 +182,7 @@ PrivateNotesEditPage.defaultProps = defaultProps; export default compose( withLocalize, - withReportAndPrivateNotesOrNotFound, + withReportAndPrivateNotesOrNotFound('privateNotes.title'), withOnyx({ personalDetailsList: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, diff --git a/src/pages/PrivateNotes/PrivateNotesListPage.js b/src/pages/PrivateNotes/PrivateNotesListPage.js index a34eb0ce596d..8e2f8c9f43e0 100644 --- a/src/pages/PrivateNotes/PrivateNotesListPage.js +++ b/src/pages/PrivateNotes/PrivateNotesListPage.js @@ -144,7 +144,7 @@ PrivateNotesListPage.displayName = 'PrivateNotesListPage'; export default compose( withLocalize, - withReportAndPrivateNotesOrNotFound, + withReportAndPrivateNotesOrNotFound('privateNotes.title'), withOnyx({ personalDetailsList: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, diff --git a/src/pages/PrivateNotes/PrivateNotesViewPage.js b/src/pages/PrivateNotes/PrivateNotesViewPage.js index 1406dfd76748..f71259a2b685 100644 --- a/src/pages/PrivateNotes/PrivateNotesViewPage.js +++ b/src/pages/PrivateNotes/PrivateNotesViewPage.js @@ -103,7 +103,7 @@ PrivateNotesViewPage.defaultProps = defaultProps; export default compose( withLocalize, - withReportAndPrivateNotesOrNotFound, + withReportAndPrivateNotesOrNotFound('privateNotes.title'), withOnyx({ personalDetailsList: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, diff --git a/src/pages/home/report/withReportAndPrivateNotesOrNotFound.js b/src/pages/home/report/withReportAndPrivateNotesOrNotFound.js index 3982dd5ab542..de5f7d36299c 100644 --- a/src/pages/home/report/withReportAndPrivateNotesOrNotFound.js +++ b/src/pages/home/report/withReportAndPrivateNotesOrNotFound.js @@ -3,14 +3,16 @@ import PropTypes from 'prop-types'; import React, {useEffect, useMemo} from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import networkPropTypes from '@components/networkPropTypes'; import {withNetwork} from '@components/OnyxProvider'; +import useLocalize from '@hooks/useLocalize'; +import usePrevious from '@hooks/usePrevious'; import * as Report from '@libs/actions/Report'; import compose from '@libs/compose'; import getComponentDisplayName from '@libs/getComponentDisplayName'; import * as ReportUtils from '@libs/ReportUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; +import LoadingPage from '@pages/LoadingPage'; import reportPropTypes from '@pages/reportPropTypes'; import ONYXKEYS from '@src/ONYXKEYS'; import withReportOrNotFound from './withReportOrNotFound'; @@ -50,81 +52,88 @@ const defaultProps = { }, }; -export default function (WrappedComponent) { +export default function (pageTitle) { // eslint-disable-next-line rulesdir/no-negated-variables - function WithReportAndPrivateNotesOrNotFound({forwardedRef, ...props}) { - const {route, report, network, session} = props; - const accountID = route.params.accountID; - const isPrivateNotesFetchTriggered = !_.isUndefined(report.isLoadingPrivateNotes); - - useEffect(() => { - // Do not fetch private notes if isLoadingPrivateNotes is already defined, or if network is offline. - if (isPrivateNotesFetchTriggered || network.isOffline) { - return; - } - - Report.getReportPrivateNote(report.reportID); - // eslint-disable-next-line react-hooks/exhaustive-deps -- do not add report.isLoadingPrivateNotes to dependencies - }, [report.reportID, network.isOffline, isPrivateNotesFetchTriggered]); - - const isPrivateNotesEmpty = accountID ? _.isEmpty(lodashGet(report, ['privateNotes', accountID, 'note'], '')) : _.isEmpty(report.privateNotes); - const shouldShowFullScreenLoadingIndicator = !isPrivateNotesFetchTriggered || (isPrivateNotesEmpty && report.isLoadingPrivateNotes); - + return (WrappedComponent) => { // eslint-disable-next-line rulesdir/no-negated-variables - const shouldShowNotFoundPage = useMemo(() => { - // Show not found view if the report is archived, or if the note is not of current user. - if (ReportUtils.isArchivedRoom(report) || (accountID && Number(session.accountID) !== Number(accountID))) { - return true; + function WithReportAndPrivateNotesOrNotFound({forwardedRef, ...props}) { + const {translate} = useLocalize(); + const {route, report, network, session} = props; + const accountID = route.params.accountID; + const isPrivateNotesFetchTriggered = !_.isUndefined(report.isLoadingPrivateNotes); + const prevIsOffline = usePrevious(network.isOffline); + const isReconnecting = prevIsOffline && !network.isOffline; + const isOtherUserNote = accountID && Number(session.accountID) !== Number(accountID); + const isPrivateNotesEmpty = accountID ? _.has(lodashGet(report, ['privateNotes', accountID, 'note'], '')) : _.isEmpty(report.privateNotes); + + useEffect(() => { + // Do not fetch private notes if isLoadingPrivateNotes is already defined, or if network is offline. + if ((isPrivateNotesFetchTriggered && !isReconnecting) || network.isOffline) { + return; + } + + Report.getReportPrivateNote(report.reportID); + // eslint-disable-next-line react-hooks/exhaustive-deps -- do not add report.isLoadingPrivateNotes to dependencies + }, [report.reportID, network.isOffline, isPrivateNotesFetchTriggered, isReconnecting]); + + const shouldShowFullScreenLoadingIndicator = !isPrivateNotesFetchTriggered || (isPrivateNotesEmpty && (report.isLoadingPrivateNotes || !isOtherUserNote)); + + // eslint-disable-next-line rulesdir/no-negated-variables + const shouldShowNotFoundPage = useMemo(() => { + // Show not found view if the report is archived, or if the note is not of current user. + if (ReportUtils.isArchivedRoom(report) || (accountID && Number(session.accountID) !== Number(accountID))) { + return true; + } + + // Don't show not found view if the notes are still loading, or if the notes are non-empty. + if (shouldShowFullScreenLoadingIndicator || !isPrivateNotesEmpty || isReconnecting) { + return false; + } + + // As notes being empty and not loading is a valid case, show not found view only in offline mode. + return network.isOffline; + }, [report, network.isOffline, accountID, session.accountID, isPrivateNotesEmpty, shouldShowFullScreenLoadingIndicator, isReconnecting]); + + if (shouldShowFullScreenLoadingIndicator) { + return ; } - // Don't show not found view if the notes are still loading, or if the notes are non-empty. - if (shouldShowFullScreenLoadingIndicator || !isPrivateNotesEmpty) { - return false; + if (shouldShowNotFoundPage) { + return ; } - // As notes being empty and not loading is a valid case, show not found view only in offline mode. - return network.isOffline; - }, [report, network.isOffline, accountID, session.accountID, isPrivateNotesEmpty, shouldShowFullScreenLoadingIndicator]); - - if (shouldShowFullScreenLoadingIndicator) { - return ; + return ( + + ); } - if (shouldShowNotFoundPage) { - return ; - } + WithReportAndPrivateNotesOrNotFound.propTypes = propTypes; + WithReportAndPrivateNotesOrNotFound.defaultProps = defaultProps; + WithReportAndPrivateNotesOrNotFound.displayName = `withReportAndPrivateNotesOrNotFound(${getComponentDisplayName(WrappedComponent)})`; - return ( - ( + - ); - } - - WithReportAndPrivateNotesOrNotFound.propTypes = propTypes; - WithReportAndPrivateNotesOrNotFound.defaultProps = defaultProps; - WithReportAndPrivateNotesOrNotFound.displayName = `withReportAndPrivateNotesOrNotFound(${getComponentDisplayName(WrappedComponent)})`; - - // eslint-disable-next-line rulesdir/no-negated-variables - const WithReportAndPrivateNotesOrNotFoundWithRef = React.forwardRef((props, ref) => ( - - )); - - WithReportAndPrivateNotesOrNotFoundWithRef.displayName = 'WithReportAndPrivateNotesOrNotFoundWithRef'; - - return compose( - withReportOrNotFound(), - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - }), - withNetwork(), - )(WithReportAndPrivateNotesOrNotFoundWithRef); + )); + + WithReportAndPrivateNotesOrNotFoundWithRef.displayName = 'WithReportAndPrivateNotesOrNotFoundWithRef'; + + return compose( + withReportOrNotFound(), + withOnyx({ + session: { + key: ONYXKEYS.SESSION, + }, + }), + withNetwork(), + )(WithReportAndPrivateNotesOrNotFoundWithRef); + }; }