From d15cd01b7b622aa5b8e80463f94c3d707f410395 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 28 Nov 2023 15:00:10 +0100 Subject: [PATCH 1/9] mark the first item in getSortedReportActions --- src/libs/ReportActionsUtils.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index bd475a57954e..22a53bb9379c 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -155,14 +155,14 @@ function isTransactionThread(parentReportAction: OnyxEntry): boole * This gives us a stable order even in the case of multiple reportActions created on the same millisecond * */ -function getSortedReportActions(reportActions: ReportAction[] | null, shouldSortInDescendingOrder = false): ReportAction[] { +function getSortedReportActions(reportActions: ReportAction[] | null, shouldSortInDescendingOrder = false, shouldMarkTheFirstItem = false): ReportAction[] { if (!Array.isArray(reportActions)) { throw new Error(`ReportActionsUtils.getSortedReportActions requires an array, received ${typeof reportActions}`); } const invertedMultiplier = shouldSortInDescendingOrder ? -1 : 1; - return reportActions?.filter(Boolean).sort((first, second) => { + const sortedActions = reportActions?.filter(Boolean).sort((first, second) => { // First sort by timestamp if (first.created !== second.created) { return (first.created < second.created ? -1 : 1) * invertedMultiplier; @@ -182,6 +182,16 @@ function getSortedReportActions(reportActions: ReportAction[] | null, shouldSort // will be consistent across all users and devices return (first.reportActionID < second.reportActionID ? -1 : 1) * invertedMultiplier; }); + + // Mark the first item if shouldMarkTheFirstItem is true + if (shouldMarkTheFirstItem && sortedActions?.length > 0) { + sortedActions[0] = { + ...sortedActions[0], + isNewestReportAction: true, + }; + } + + return sortedActions; } /** @@ -448,7 +458,7 @@ function getSortedReportActionsForDisplay(reportActions: ReportActions | null): .filter(([key, reportAction]) => shouldReportActionBeVisible(reportAction, key)) .map((entry) => entry[1]); const baseURLAdjustedReportActions = filteredReportActions.map((reportAction) => replaceBaseURL(reportAction)); - return getSortedReportActions(baseURLAdjustedReportActions, true); + return getSortedReportActions(baseURLAdjustedReportActions, true, true); } /** From c476637583c1dec220ae04427b36bd10bd1f3d72 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 28 Nov 2023 15:01:24 +0100 Subject: [PATCH 2/9] update type ReportActionBase --- src/types/onyx/ReportAction.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 891a0ffcb7b8..d407275f614a 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -50,6 +50,9 @@ type Message = { /** ID of a task report */ taskReportID?: string; + + /** We manually add this field while sorting to detect the end of the list */ + isNewestReportAction?: boolean; }; type Person = { From 69223cac5accc93cdffe390d01027fa588d5c51e Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 28 Nov 2023 15:08:03 +0100 Subject: [PATCH 3/9] use isNewestReportAction for loadNewerChats --- src/pages/home/report/ReportActionsView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index b4d21de919bf..6f46a6616745 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -96,6 +96,7 @@ function ReportActionsView(props) { const isFocused = useIsFocused(); const reportID = props.report.reportID; + const isNewestReportAction = lodashGet(props.reportActions[0], 'isNewestReportAction'); /** * @returns {Boolean} @@ -199,7 +200,7 @@ function ReportActionsView(props) { const loadNewerChats = useMemo( () => _.throttle(({distanceFromStart}) => { - if (props.isLoadingNewerReportActions || props.isLoadingInitialReportActions) { + if (props.isLoadingNewerReportActions || props.isLoadingInitialReportActions || isNewestReportAction) { return; } @@ -221,7 +222,7 @@ function ReportActionsView(props) { const newestReportAction = _.first(props.reportActions); Report.getNewerActions(reportID, newestReportAction.reportActionID); }, 500), - [props.isLoadingNewerReportActions, props.isLoadingInitialReportActions, props.reportActions, reportID], + [props.isLoadingNewerReportActions, props.isLoadingInitialReportActions, props.reportActions, reportID, isNewestReportAction], ); /** From 683aa4eab2f87f1c65fa4c790a207509c52cc056 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 28 Nov 2023 16:56:40 +0100 Subject: [PATCH 4/9] fix types --- src/types/onyx/ReportAction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index d407275f614a..0668ce58ccb3 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -50,9 +50,6 @@ type Message = { /** ID of a task report */ taskReportID?: string; - - /** We manually add this field while sorting to detect the end of the list */ - isNewestReportAction?: boolean; }; type Person = { @@ -141,6 +138,9 @@ type ReportActionBase = { isAttachment?: boolean; childRecentReceiptTransactionIDs?: Record; reportID?: string; + + /** We manually add this field while sorting to detect the end of the list */ + isNewestReportAction?: boolean; }; type ReportAction = ReportActionBase & OriginalMessage; From 2c702412e0279cd3891511aecd7d0628a4e1b196 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 29 Nov 2023 08:07:17 +0100 Subject: [PATCH 5/9] tests --- src/libs/ReportActionsUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 22a53bb9379c..781392304acc 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -183,7 +183,7 @@ function getSortedReportActions(reportActions: ReportAction[] | null, shouldSort return (first.reportActionID < second.reportActionID ? -1 : 1) * invertedMultiplier; }); - // Mark the first item if shouldMarkTheFirstItem is true + // If shouldMarkTheFirstItem is true, label the first reportAction as isNewestReportAction if (shouldMarkTheFirstItem && sortedActions?.length > 0) { sortedActions[0] = { ...sortedActions[0], From 5bd131485f9848d8f16b5d53f839fb1a97cc5756 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 29 Nov 2023 08:34:36 +0100 Subject: [PATCH 6/9] update getSortedReportActionsForDisplay --- src/libs/ReportActionsUtils.ts | 10 +++++----- src/pages/home/ReportScreen.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 781392304acc..08b5ac49f301 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -155,7 +155,7 @@ function isTransactionThread(parentReportAction: OnyxEntry): boole * This gives us a stable order even in the case of multiple reportActions created on the same millisecond * */ -function getSortedReportActions(reportActions: ReportAction[] | null, shouldSortInDescendingOrder = false, shouldMarkTheFirstItem = false): ReportAction[] { +function getSortedReportActions(reportActions: ReportAction[] | null, shouldSortInDescendingOrder = false, shouldMarkTheFirstItemAsNewest = false): ReportAction[] { if (!Array.isArray(reportActions)) { throw new Error(`ReportActionsUtils.getSortedReportActions requires an array, received ${typeof reportActions}`); } @@ -183,8 +183,8 @@ function getSortedReportActions(reportActions: ReportAction[] | null, shouldSort return (first.reportActionID < second.reportActionID ? -1 : 1) * invertedMultiplier; }); - // If shouldMarkTheFirstItem is true, label the first reportAction as isNewestReportAction - if (shouldMarkTheFirstItem && sortedActions?.length > 0) { + // If shouldMarkTheFirstItemAsNewest is true, label the first reportAction as isNewestReportAction + if (shouldMarkTheFirstItemAsNewest && sortedActions?.length > 0) { sortedActions[0] = { ...sortedActions[0], isNewestReportAction: true, @@ -453,12 +453,12 @@ function filterOutDeprecatedReportActions(reportActions: ReportActions | null): * to ensure they will always be displayed in the same order (in case multiple actions have the same timestamp). * This is all handled with getSortedReportActions() which is used by several other methods to keep the code DRY. */ -function getSortedReportActionsForDisplay(reportActions: ReportActions | null): ReportAction[] { +function getSortedReportActionsForDisplay(reportActions: ReportActions | null, shouldMarkTheFirstItemAsNewest = false): ReportAction[] { const filteredReportActions = Object.entries(reportActions ?? {}) .filter(([key, reportAction]) => shouldReportActionBeVisible(reportAction, key)) .map((entry) => entry[1]); const baseURLAdjustedReportActions = filteredReportActions.map((reportAction) => replaceBaseURL(reportAction)); - return getSortedReportActions(baseURLAdjustedReportActions, true, true); + return getSortedReportActions(baseURLAdjustedReportActions, true, shouldMarkTheFirstItemAsNewest); } /** diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 33646e7129cd..782681fdf55b 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -474,7 +474,7 @@ export default compose( reportActions: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getReportID(route)}`, canEvict: false, - selector: ReportActionsUtils.getSortedReportActionsForDisplay, + selector: (reportActions) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true), }, report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${getReportID(route)}`, From ff1c9f367e147b1f848483d2d6cd39d83bd90825 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 29 Nov 2023 08:47:37 +0100 Subject: [PATCH 7/9] update test --- tests/unit/ReportActionsUtilsTest.js | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/unit/ReportActionsUtilsTest.js b/tests/unit/ReportActionsUtilsTest.js index 9973515c44de..dcc71668a823 100644 --- a/tests/unit/ReportActionsUtilsTest.js +++ b/tests/unit/ReportActionsUtilsTest.js @@ -185,10 +185,69 @@ describe('ReportActionsUtils', () => { message: [{html: 'I have changed the task'}], }, ]; + const result = ReportActionsUtils.getSortedReportActionsForDisplay(input); input.pop(); expect(result).toStrictEqual(input); }); + + describe('getSortedReportActionsForDisplay with marked the first reportAction', () => { + it('should filter out non-whitelisted actions', () => { + const input = [ + { + created: '2022-11-13 22:27:01.825', + reportActionID: '8401445780099176', + actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-12 22:27:01.825', + reportActionID: '6401435781022176', + actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-11 22:27:01.825', + reportActionID: '2962390724708756', + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-10 22:27:01.825', + reportActionID: '1609646094152486', + actionName: CONST.REPORT.ACTIONS.TYPE.RENAMED, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-09 22:27:01.825', + reportActionID: '8049485084562457', + actionName: CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.UPDATE_FIELD, + message: [{html: 'updated the Approval Mode from "Submit and Approve" to "Submit and Close"'}], + }, + { + created: '2022-11-08 22:27:06.825', + reportActionID: '1661970171066216', + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED, + message: [{html: 'Waiting for the bank account'}], + }, + { + created: '2022-11-06 22:27:08.825', + reportActionID: '1661970171066220', + actionName: CONST.REPORT.ACTIONS.TYPE.TASKEDITED, + message: [{html: 'I have changed the task'}], + }, + ]; + + const resultWithoutNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input); + const resultWithNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input, true); + input.pop(); + // Mark the newest report action as the newest report action + resultWithoutMark[0] = { + ...resultWithoutMark[0], + isNewestReportAction: true, + }; + expect(resultWithoutNewestFlag).toStrictEqual(resultWithNewestFlag); + }); it('should filter out closed actions', () => { const input = [ { From e6b6ed82054fd82acbf8fadc01b96faed02dde0f Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 29 Nov 2023 09:13:05 +0100 Subject: [PATCH 8/9] lint --- tests/unit/ReportActionsUtilsTest.js | 112 ++++++++++++++------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/tests/unit/ReportActionsUtilsTest.js b/tests/unit/ReportActionsUtilsTest.js index dcc71668a823..b8b6eb5e7673 100644 --- a/tests/unit/ReportActionsUtilsTest.js +++ b/tests/unit/ReportActionsUtilsTest.js @@ -191,63 +191,65 @@ describe('ReportActionsUtils', () => { expect(result).toStrictEqual(input); }); - describe('getSortedReportActionsForDisplay with marked the first reportAction', () => { - it('should filter out non-whitelisted actions', () => { - const input = [ - { - created: '2022-11-13 22:27:01.825', - reportActionID: '8401445780099176', - actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, - message: [{html: 'Hello world'}], - }, - { - created: '2022-11-12 22:27:01.825', - reportActionID: '6401435781022176', - actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, - message: [{html: 'Hello world'}], - }, - { - created: '2022-11-11 22:27:01.825', - reportActionID: '2962390724708756', - actionName: CONST.REPORT.ACTIONS.TYPE.IOU, - message: [{html: 'Hello world'}], - }, - { - created: '2022-11-10 22:27:01.825', - reportActionID: '1609646094152486', - actionName: CONST.REPORT.ACTIONS.TYPE.RENAMED, - message: [{html: 'Hello world'}], - }, - { - created: '2022-11-09 22:27:01.825', - reportActionID: '8049485084562457', - actionName: CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.UPDATE_FIELD, - message: [{html: 'updated the Approval Mode from "Submit and Approve" to "Submit and Close"'}], - }, - { - created: '2022-11-08 22:27:06.825', - reportActionID: '1661970171066216', - actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED, - message: [{html: 'Waiting for the bank account'}], - }, - { - created: '2022-11-06 22:27:08.825', - reportActionID: '1661970171066220', - actionName: CONST.REPORT.ACTIONS.TYPE.TASKEDITED, - message: [{html: 'I have changed the task'}], - }, - ]; + describe('getSortedReportActionsForDisplay with marked the first reportAction', () => { + it('should filter out non-whitelisted actions', () => { + const input = [ + { + created: '2022-11-13 22:27:01.825', + reportActionID: '8401445780099176', + actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-12 22:27:01.825', + reportActionID: '6401435781022176', + actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-11 22:27:01.825', + reportActionID: '2962390724708756', + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-10 22:27:01.825', + reportActionID: '1609646094152486', + actionName: CONST.REPORT.ACTIONS.TYPE.RENAMED, + message: [{html: 'Hello world'}], + }, + { + created: '2022-11-09 22:27:01.825', + reportActionID: '8049485084562457', + actionName: CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.UPDATE_FIELD, + message: [{html: 'updated the Approval Mode from "Submit and Approve" to "Submit and Close"'}], + }, + { + created: '2022-11-08 22:27:06.825', + reportActionID: '1661970171066216', + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED, + message: [{html: 'Waiting for the bank account'}], + }, + { + created: '2022-11-06 22:27:08.825', + reportActionID: '1661970171066220', + actionName: CONST.REPORT.ACTIONS.TYPE.TASKEDITED, + message: [{html: 'I have changed the task'}], + }, + ]; - const resultWithoutNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input); - const resultWithNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input, true); - input.pop(); - // Mark the newest report action as the newest report action - resultWithoutMark[0] = { - ...resultWithoutMark[0], - isNewestReportAction: true, - }; - expect(resultWithoutNewestFlag).toStrictEqual(resultWithNewestFlag); + const resultWithoutNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input); + const resultWithNewestFlag = ReportActionsUtils.getSortedReportActionsForDisplay(input, true); + input.pop(); + // Mark the newest report action as the newest report action + resultWithoutNewestFlag[0] = { + ...resultWithoutNewestFlag[0], + isNewestReportAction: true, + }; + expect(resultWithoutNewestFlag).toStrictEqual(resultWithNewestFlag); + }); }); + it('should filter out closed actions', () => { const input = [ { From cc68278b03756482dac7eb513d36d0a742966fc1 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 6 Dec 2023 18:29:37 +0100 Subject: [PATCH 9/9] update naming --- src/pages/home/report/ReportActionsView.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index 6f46a6616745..d7eaaa340e05 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -96,7 +96,7 @@ function ReportActionsView(props) { const isFocused = useIsFocused(); const reportID = props.report.reportID; - const isNewestReportAction = lodashGet(props.reportActions[0], 'isNewestReportAction'); + const hasNewestReportAction = lodashGet(props.reportActions[0], 'isNewestReportAction'); /** * @returns {Boolean} @@ -200,7 +200,7 @@ function ReportActionsView(props) { const loadNewerChats = useMemo( () => _.throttle(({distanceFromStart}) => { - if (props.isLoadingNewerReportActions || props.isLoadingInitialReportActions || isNewestReportAction) { + if (props.isLoadingNewerReportActions || props.isLoadingInitialReportActions || hasNewestReportAction) { return; } @@ -222,7 +222,7 @@ function ReportActionsView(props) { const newestReportAction = _.first(props.reportActions); Report.getNewerActions(reportID, newestReportAction.reportActionID); }, 500), - [props.isLoadingNewerReportActions, props.isLoadingInitialReportActions, props.reportActions, reportID, isNewestReportAction], + [props.isLoadingNewerReportActions, props.isLoadingInitialReportActions, props.reportActions, reportID, hasNewestReportAction], ); /**