Skip to content
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
24 changes: 23 additions & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7378,12 +7378,33 @@ function buildOptimisticMoneyRequestEntities({
return [createdActionForChat, createdActionForIOUReport, iouAction, transactionThread, createdActionForTransactionThread];
}

// Check if the report is empty, meaning it has no visible messages (i.e. only a "created" report action).
/**
* Check if the report is empty, meaning it has no visible messages (i.e. only a "created" report action).
* Added caching mechanism via derived values.
*/
function isEmptyReport(report: OnyxEntry<Report>): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB, but if all that isEmptyReport does is add caching on top generateEmptyReport, wouldn't it make more sense to concatenate them into a single function? Something like:

function isEmptyReport(report: OnyxEntry<Report>, useCache = true): boolean {
    if (!report) {
        return true;
    }

    if (useCache && reportAttributes?.[report.reportID]) {
        return reportAttributes?.[report.reportID].isEmpty;
    }

    if (report.lastMessageText) {
        return false;
    }
    
    const lastVisibleMessage = getLastVisibleMessage(report.reportID);
    return !lastVisibleMessage.lastMessageText;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mjasikowski, thanks for the comment!

Why we need to separate them into two is that when generating reportAttributes under OnyxDerived, we need to make sure it is fresh value. In other words, we need to force cache refresh when cache expires.

I have followed the pattern that was used with generateReportName + getReportName combo.

Let me know if that makes sense, thanks!

if (!report) {
return true;
}

// Get the `isEmpty` state from cached report attributes
const attributes = reportAttributes?.[report.reportID];
if (attributes) {
return attributes.isEmpty;
}

return generateIsEmptyReport(report);
}

/**
* Check if the report is empty, meaning it has no visible messages (i.e. only a "created" report action).
* No cache implementation which bypasses derived value check.
*/
function generateIsEmptyReport(report: OnyxEntry<Report>): boolean {
if (!report) {
return true;
}

if (report.lastMessageText) {
return false;
}
Expand Down Expand Up @@ -10772,6 +10793,7 @@ export {
isDefaultRoom,
isDeprecatedGroupDM,
isEmptyReport,
generateIsEmptyReport,
isRootGroupChat,
isExpenseReport,
isExpenseRequest,
Expand Down
3 changes: 2 additions & 1 deletion src/libs/actions/OnyxDerived/configs/reportAttributes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {generateReportAttributes, generateReportName, isValidReport} from '@libs/ReportUtils';
import {generateIsEmptyReport, generateReportAttributes, generateReportName, isValidReport} from '@libs/ReportUtils';
import SidebarUtils from '@libs/SidebarUtils';
import createOnyxDerivedValueConfig from '@userActions/OnyxDerived/createOnyxDerivedValueConfig';
import hasKeyTriggeredCompute from '@userActions/OnyxDerived/utils';
Expand Down Expand Up @@ -107,6 +107,7 @@ export default createOnyxDerivedValueConfig({

acc[report.reportID] = {
reportName: generateReportName(report),
isEmpty: generateIsEmptyReport(report),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you contribute to the unit test for Derived value here?

Copy link
Contributor Author

@kacper-mikolajczak kacper-mikolajczak May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I tried to add another test, but I've noticed that the tests are not working as expected (they are not failing regardless of assertion made). Will address it (and contact Tomek to double check if there is indeed a regression) and get back to you when resolved 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out is something with async nature of tests because they are not correctly fulfilled (the async callback is not even ran).

Also, what would might help is waiting for Onyx.clear() in beforeEach.

We are still trying to figure out 100% what's happening.

brickRoadStatus,
};

Expand Down
4 changes: 4 additions & 0 deletions src/types/onyx/DerivedValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ type ReportAttributes = {
* The name of the report.
*/
reportName: string;
/**
* Whether the report is empty (has no visible messages).
*/
isEmpty: boolean;
/**
* The status of the brick road.
*/
Expand Down
1 change: 1 addition & 0 deletions tests/unit/navigateAfterOnboardingTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jest.mock('@libs/ReportUtils', () => ({
getAllReportActionsErrorsAndReportActionThatRequiresAttention: jest.requireActual<typeof ReportUtils>('@libs/ReportUtils').getAllReportActionsErrorsAndReportActionThatRequiresAttention,
getAllReportErrors: jest.requireActual<typeof ReportUtils>('@libs/ReportUtils').getAllReportErrors,
shouldDisplayViolationsRBRInLHN: jest.requireActual<typeof ReportUtils>('@libs/ReportUtils').shouldDisplayViolationsRBRInLHN,
generateIsEmptyReport: jest.requireActual<typeof ReportUtils>('@libs/ReportUtils').generateIsEmptyReport,
}));

jest.mock('@libs/Navigation/helpers/shouldOpenOnAdminRoom', () => ({
Expand Down
Loading