From 4aaf3e3f1d60f006e122ad40fb5a74ed43e3802c Mon Sep 17 00:00:00 2001
From: Roji Philip <rojiphil@gmail.com>
Date: Mon, 6 Nov 2023 14:13:48 +0530
Subject: [PATCH 1/3] optimistically add lastvisibleactioncreated

---
 src/libs/ReportUtils.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 1e3fc5297193..ed338991b91f 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -2422,6 +2422,7 @@ function buildOptimisticIOUReport(payeeAccountID, payerAccountID, total, chatRep
         reportName: `${payerEmail} owes ${formattedTotal}`,
         notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
         parentReportID: chatReportID,
+        lastVisibleActionCreated: DateUtils.getDBTime(),
     };
 }
 
@@ -2461,6 +2462,7 @@ function buildOptimisticExpenseReport(chatReportID, policyID, payeeAccountID, to
         total: storedTotal,
         notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
         parentReportID: chatReportID,
+        lastVisibleActionCreated: DateUtils.getDBTime(),
     };
 }
 
@@ -3132,6 +3134,7 @@ function buildOptimisticTaskReport(ownerAccountID, assigneeAccountID = 0, parent
         stateNum: CONST.REPORT.STATE_NUM.OPEN,
         statusNum: CONST.REPORT.STATUS.OPEN,
         notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
+        lastVisibleActionCreated: DateUtils.getDBTime(),
     };
 }
 

From 729e585f86dc8ee1a0899fa5b687669dfaf21a5c Mon Sep 17 00:00:00 2001
From: Roji Philip <rojiphil@gmail.com>
Date: Wed, 8 Nov 2023 23:05:30 +0530
Subject: [PATCH 2/3] Added SidebarOrder Unit Tests

---
 tests/unit/SidebarOrderTest.js | 175 +++++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)

diff --git a/tests/unit/SidebarOrderTest.js b/tests/unit/SidebarOrderTest.js
index e9caed9f3dc7..6eef3e40bf1c 100644
--- a/tests/unit/SidebarOrderTest.js
+++ b/tests/unit/SidebarOrderTest.js
@@ -242,6 +242,181 @@ describe('Sidebar', () => {
             );
         });
 
+        it('reorders the reports to have a newly created task report on top', () => {
+            // Given three reports in the recently updated order of 3, 2, 1
+            const report1 = LHNTestUtils.getFakeReport([1, 2], 4);
+            const report2 = LHNTestUtils.getFakeReport([3, 4], 3);
+            const report3 = LHNTestUtils.getFakeReport([5, 6], 2);
+
+            const taskReportName = 'Buy Grocery';
+            const taskReport = {
+                ...LHNTestUtils.getFakeReport([7, 8], 1),
+                type: CONST.REPORT.TYPE.TASK,
+                reportName: taskReportName,
+                managerID: 2,
+                stateNum: CONST.REPORT.STATE_NUM.OPEN,
+                statusNum: CONST.REPORT.STATUS.OPEN,
+            };
+
+            // Each report has at least one ADDCOMMENT action so should be rendered in the LNH
+            Report.addComment(report1.reportID, 'Hi, this is a comment');
+            Report.addComment(report2.reportID, 'Hi, this is a comment');
+            Report.addComment(report3.reportID, 'Hi, this is a comment');
+
+            LHNTestUtils.getDefaultRenderedSidebarLinks(taskReport.reportID);
+
+            return (
+                waitForBatchedUpdates()
+                    // When Onyx is updated with the data and the sidebar re-renders
+                    .then(() =>
+                        Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
+                            [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                            [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`]: report1,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report2.reportID}`]: report2,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report3.reportID}`]: report3,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${taskReport.reportID}`]: taskReport,
+                        }),
+                    )
+
+                    // Then the order of the reports should be 4 > 3 > 2 > 1
+                    .then(() => {
+                        const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames');
+                        const displayNames = screen.queryAllByLabelText(hintText);
+                        expect(displayNames).toHaveLength(4);
+                        expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe(taskReportName);
+                        expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six');
+                        expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four');
+                        expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two');
+                    })
+            );
+        });
+
+        it('reorders the reports to have a newly created iou report on top', () => {
+            // Given three reports in the recently updated order of 3, 2, 1
+            const report1 = LHNTestUtils.getFakeReport([1, 2], 4);
+            const report2 = LHNTestUtils.getFakeReport([3, 4], 3);
+            const report3 = {
+                ...LHNTestUtils.getFakeReport([5, 6], 2),
+                hasOutstandingChildRequest: false,
+
+                // This has to be added after the IOU report is generated
+                iouReportID: null,
+            };
+            const iouReport = {
+                ...LHNTestUtils.getFakeReport([7, 8], 1),
+                type: CONST.REPORT.TYPE.IOU,
+                ownerAccountID: 2,
+                managerID: 2,
+                hasOutstandingIOU: true,
+                hasOutstandingChildRequest: true,
+                total: 10000,
+                currency: 'USD',
+                chatReportID: report3.reportID,
+            };
+            report3.iouReportID = iouReport.reportID;
+
+            // Each report has at least one ADDCOMMENT action so should be rendered in the LNH
+            Report.addComment(report1.reportID, 'Hi, this is a comment');
+            Report.addComment(report2.reportID, 'Hi, this is a comment');
+            Report.addComment(report3.reportID, 'Hi, this is a comment');
+
+            LHNTestUtils.getDefaultRenderedSidebarLinks(report3.reportID);
+
+            return (
+                waitForBatchedUpdates()
+                    // When Onyx is updated with the data and the sidebar re-renders
+                    .then(() =>
+                        Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
+                            [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                            [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`]: report1,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report2.reportID}`]: report2,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report3.reportID}`]: report3,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`]: iouReport,
+                        }),
+                    )
+
+                    // Then the order of the reports should be 4 > 3 > 2 > 1
+                    .then(() => {
+                        const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames');
+                        const displayNames = screen.queryAllByLabelText(hintText);
+                        expect(displayNames).toHaveLength(4);
+                        expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Email Two owes $100.00');
+                        expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six');
+                        expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four');
+                        expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two');
+                    })
+            );
+        });
+
+        it('reorders the reports to have a newly created expense report on top', () => {
+            // Given three reports in the recently updated order of 3, 2, 1
+            const report1 = LHNTestUtils.getFakeReport([1, 2], 4);
+            const report2 = LHNTestUtils.getFakeReport([3, 4], 3);
+            const fakeReport = LHNTestUtils.getFakeReportWithPolicy([5, 6], 2);
+            const fakePolicy = LHNTestUtils.getFakePolicy(fakeReport.policyID);
+            const report3 = {
+                ...fakeReport,
+                hasOutstandingChildRequest: false,
+
+                // This has to be added after the IOU report is generated
+                iouReportID: null,
+            };
+            const expenseReport = {
+                ...LHNTestUtils.getFakeReport([7, 8], 1),
+                type: CONST.REPORT.TYPE.EXPENSE,
+                ownerAccountID: 7,
+                managerID: 7,
+                policyName: 'Workspace',
+                hasOutstandingIOU: true,
+                total: -10000,
+                currency: 'USD',
+                state: CONST.REPORT.STATE.SUBMITTED,
+                stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
+                chatReportID: report3.reportID,
+                parentReportID: report3.reportID,
+            };
+            report3.iouReportID = expenseReport.reportID;
+
+            // Each report has at least one ADDCOMMENT action so should be rendered in the LNH
+            Report.addComment(report1.reportID, 'Hi, this is a comment');
+            Report.addComment(report2.reportID, 'Hi, this is a comment');
+            Report.addComment(report3.reportID, 'Hi, this is a comment');
+
+            LHNTestUtils.getDefaultRenderedSidebarLinks(report3.reportID);
+
+            return (
+                waitForBatchedUpdates()
+                    // When Onyx is updated with the data and the sidebar re-renders
+                    .then(() =>
+                        Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
+                            [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                            [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
+                            [`${ONYXKEYS.COLLECTION.POLICY}${fakeReport.policyID}`]: fakePolicy,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`]: report1,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report2.reportID}`]: report2,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${report3.reportID}`]: report3,
+                            [`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`]: expenseReport,
+                        }),
+                    )
+
+                    // Then the order of the reports should be 4 > 3 > 2 > 1
+                    .then(() => {
+                        const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames');
+                        const displayNames = screen.queryAllByLabelText(hintText);
+                        expect(displayNames).toHaveLength(4);
+                        expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Workspace owes $100.00');
+                        expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Email Five');
+                        expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four');
+                        expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two');
+                    })
+            );
+        });
+
         it('reorders the reports to keep draft reports on top', () => {
             // Given three reports in the recently updated order of 3, 2, 1
             // And the second report has a draft

From ad283e03aa4e26d57d1237b6ced8c71118aeb073 Mon Sep 17 00:00:00 2001
From: Roji Philip <rojiphil@gmail.com>
Date: Mon, 27 Nov 2023 22:41:04 +0530
Subject: [PATCH 3/3] Add type for lastVisibleActionCreated

---
 src/libs/ReportUtils.ts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 12f9cd6e504a..03d029d7c00d 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -113,6 +113,7 @@ type OptimisticExpenseReport = Pick<
     | 'total'
     | 'notificationPreference'
     | 'parentReportID'
+    | 'lastVisibleActionCreated'
 >;
 
 type OptimisticIOUReportAction = Pick<
@@ -268,6 +269,7 @@ type OptimisticTaskReport = Pick<
     | 'stateNum'
     | 'statusNum'
     | 'notificationPreference'
+    | 'lastVisibleActionCreated'
 >;
 
 type TransactionDetails =
@@ -306,6 +308,7 @@ type OptimisticIOUReport = Pick<
     | 'notificationPreference'
     | 'parentReportID'
     | 'statusNum'
+    | 'lastVisibleActionCreated'
 >;
 type DisplayNameWithTooltips = Array<Pick<PersonalDetails, 'accountID' | 'pronouns' | 'displayName' | 'login' | 'avatar'>>;
 
