Skip to content

Synced the message preview between Search router and LHN - #79278

Merged
mountiny merged 12 commits into
Expensify:mainfrom
suhailpthaj:fix/78217
Feb 11, 2026
Merged

mountiny merged 12 commits into
Expensify:mainfrom
suhailpthaj:fix/78217

Conversation

@suhailpthaj

@suhailpthaj suhailpthaj commented Jan 10, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Showing the same message preview in LHN and Search router, i.e:

  1. For empty report -> "No activity yet".
  2. During receipt scanning -> Receipt scanning...
  3. After receipt scanning -> The message preview or last message returned from backend.

Fixed Issues

$ #78217
PROPOSAL: #78217 (comment)

Tests

  1. Go to the app.
  2. Click on FAB then select start chat.
  3. Select the person (to chat with) with whom you never chat or you can select the workspace chat as well.
  4. Create an empty report and pin the created empty report.
  5. Verify that the message preview of empty report shows "No activity yet" in the Search router and in LHN.
  6. Create a scanned expense in the created empty report.
  7. Verify that the message preview of the expense report shows "Receipt scanning..." in the Search router and in LHN during receipt scanning.
  8. Verify that the the message preview of the expense report shows the message returned from backend about the receipt or expense and the message preview is same between LHN and in Search router after scanning.
  • Verify that no errors appear in the JS console

Offline tests

Same as tests

QA Steps

Same as tests

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android-native.mp4
Android: mWeb Chrome
Android-mweb.mp4
iOS: Native
ios-native.mp4
iOS: mWeb Safari
ios-mWeb-safari.mp4
MacOS: Chrome / Safari
Scan-expense-issue-recording.mp4

@suhailpthaj
suhailpthaj requested review from a team as code owners January 10, 2026 10:22
@melvin-bot
melvin-bot Bot requested review from suneox and trjExpensify and removed request for a team January 10, 2026 10:22
@melvin-bot

melvin-bot Bot commented Jan 10, 2026

Copy link
Copy Markdown

@suneox Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6da6da6b7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 847 to 849
// If the last action differs from last original action, it means there's a hidden action (like a whisper), then use getLastVisibleMessage to get the preview text
if (!lastMessageTextFromReport && !lastReportAction && !!lastOriginalReportAction) {
if (!lastMessageTextFromReport && !lastReportAction && !!lastOriginalReportAction && isWhisperAction(lastOriginalReportAction)) {
return lastVisibleMessage?.lastMessageText ?? '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve hidden-action filtering for non-whispers

This new isWhisperAction guard means we only fall back to getLastVisibleMessage when the hidden last action is a whisper; for any other hidden action, we now fall through to report.lastMessageText. That can surface actions that shouldReportActionBeVisible intentionally hides for permission reasons (e.g., ACTIONABLE_CARD_FRAUD_ALERT is hidden when canUserPerformWriteAction is false in ReportActionsUtils.ts 1070–1077), so a user without write permission could see the alert text in LHN/search previews despite the visibility gate. The previous logic returned the last visible message (empty in this case), so this change effectively bypasses the visibility filter for non-whisper hidden actions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@suneox @suhailpthaj What about this comment? What about other cases of hidden report actions that are not whisper - canUserPerformWriteAction is false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mountiny Reverted this change.

@trjExpensify trjExpensify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this PR is making some unintended changes, and just having Expense as the subtext of a report has the potential to introduce confusion between expenses and reports - as it seemingly appears to label the report as an "Expense".

Looking at the OP of the parent issue, the bug was that the amount in the search router preview doesn't update reliably to incl. the value of the expense in the title after it completes receipt scanning. We should focus on that.

image

@suhailpthaj

suhailpthaj commented Jan 12, 2026

Copy link
Copy Markdown
Contributor Author

@trjExpensify
We aren't showing Expense explicitly in this PR.

This PR introduces return in getLastMessageTextForReport function for whispers to prevent the join message by concierge.

But this PR loosely guarded the whisper filtering which leads to letting the non whisper code enter in the snippet and return the lastVisibleMessage.

Before this PR, the application was running with Expense and showing Expense as message preview.

We are just guarding it strongly or preventing the code going inside the added conditions (in the PR) which was made to whispers not expenses.

The backend fix is already being handled by @getusha

cc: @mountiny

@trjExpensify

trjExpensify commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

Yeah, I'm going to need Vit's input. I don't see why changing $20.00 expense to Expense has anything to do with whispers, and the explanation of changes for this PR is simply:

Showing Expense instead of currency amount expense as message preview in search for IOU.

@suneox

suneox commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

Yeah, I'm going to need Vit's input. I don't see why changing $20.00 expense to Expense has anything to do with whispers, and the explanation of changes for this PR is simply:

Showing Expense instead of currency amount expense as message preview in search for IOU.

@trjExpensify I’d like some clarification on the suggestion to show the message preview as Expense when there is no chat or activity on the expense. The goal is to keep the message preview consistent with the current behavior before opening the expense details.

Message preview
CleanShot.2026-01-14.at.00.07.08.mp4

Please correct me if I'm wrong — should we instead keep the message preview consistent as {currency} {amount} expense rather than Expense in this case?

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

@mountiny We need your input here in the discussion. Can you please clarify the confusion. I mentioned the PR here

@trjExpensify

Copy link
Copy Markdown
Contributor

Yeah, so maybe to recap for @mountiny where I'm at with the status quo for expense reports (and by extension IOUReports where applicable):

  • Empty: "No activity yet"
  • Scanning: "Receipt scanning..."
  • Added an expense manually / scan completed: "£10.00 expense"

@trjExpensify I’d like some clarification on #78217 (comment) to show the message preview as Expense when there is no chat or activity on the expense. The goal is to keep the message preview consistent with the current behavior before opening the expense details.

Just to restate the question to ensure I'm interpreting you correctly. The question is:

  • What should the preview of an empty expense report read?

If that's the question, then historically it has been the standard "No activity yet". I'm unaware of where a conscious product change/decision was made to change that. Feel free to point me in that direction of somewhere, if so! I do see on staging this looks broken in a few ways:

  1. It reads "No activity yet" first then quickly changes to "This chat is with ". It's not a "chat" though, it's an expense report. So this is strange.
  2. The preview in the search router doesn't match the LHN preview, and there it reads "Expense". It's not an expense though, it's an Expense report.
2026-01-14_02-06-10.mp4

A couple of other observations downstream..

  1. As soon as I add an expense to the report, it updates first to "submitted £10.00" and then to £10 expense accordingly.
  2. When the receipt is scanning, it reads Submitted £0.00 > then £0.00 expense > then $20.00 expense accordingly.
2026-01-14_02-16-53.mp4

@mountiny

Copy link
Copy Markdown
Contributor

I agree that the preview of the last message should match between LHN and Search router.

Regarding the:

  • Empty: "No activity yet"
  • Scanning: "Receipt scanning..."
  • Added an expense manually / scan completed: "£10.00 expense"

Added an expense manually / scan completed: "£10.00 expense"

I think what makes it hard to follow are the three levels we can have: the workspace chat > Expense report > Transaction thread.

But I agree these 3 messages should be there as the preview of the last action on the EXPENSE REPORT, not on the transaction thread or workspace chat

@codecov

codecov Bot commented Jan 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/libs/OptionsListUtils/index.ts 81.17% <88.88%> (+3.17%) ⬆️
... and 78 files with indirect coverage changes

@trjExpensify

Copy link
Copy Markdown
Contributor

But I agree these 3 messages should be there as the preview of the last action on the EXPENSE REPORT, not on the transaction thread or workspace chat

Yeah, I'm only talking about the report here, not the others. 👍

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

@trjExpensify What we are gonna do now with this PR?

Should we move ahead with this PR and create an another follow up issue in which we will achieve the behaviour among LHN and search router which you have mentioned?

One thing I wanna say, Expense isn't the last message, it is the alternate text and it will be shown as message preview as fallback if last message isn't available.

@trjExpensify

Copy link
Copy Markdown
Contributor

Empty: "No activity yet"
Scanning: "Receipt scanning..."
Added an expense manually / scan completed: "£10.00 expense"

I think we should do it in this PR, because this PR is changing it to show Expense when an expense is added to the report.

@mountiny

Copy link
Copy Markdown
Contributor

So seems like for empty report, we want to make sure both LHN and search will show No activity yet, that was wrong in your video:

It reads "No activity yet" first then quickly changes to "This chat is with ". It's not a "chat" though, it's an expense report. So this is strange.

Then:

  1. Click on Search icon (before and after the scanning is completed).
  2. Verify that the message preview of the created scanned expense displays Expense instead of currency amount expense, (before and after the scanning is completed).

In this case, the previous should not be Expense, but Receipt scanning...

And then for:

  1. Now create a manual expense in that 1:1 chat.
  2. Click on Search icon.
  3. Verify that the message preview of the created manual expense displays Expense instead of currency amount expense.

The preview should show £10.00 expense

@suhailpthaj That is the expected behaviour, can you please update the test steps and update the code to match that? cc @suneox

Thank you!

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

On it.

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

@mountiny Can you please have a look at backend PR created by @getusha

It is required to achieve this expected behaviour.

The preview should show £10.00 expense

@trjExpensify The following expected behaviour I covered:

we want to make sure both LHN and search will show No activity yet
In this case, the previous should not be Expense, but Receipt scanning...

Now it is matching between LHN and Search router for Expense reports instead of always showing Expense.

I have couple of doubts which I'll ask later. I'll also give the reasoning of why these issues were occuring, reported by you.

@mountiny

Copy link
Copy Markdown
Contributor

@getusha PR still needs some work https://github.com/Expensify/Auth/pull/19268

@suhailpthaj

suhailpthaj commented Jan 31, 2026

Copy link
Copy Markdown
Contributor Author

@trjExpensify @mountiny Backend PR has been merged.

As per the expected behaviour mentioned by @trjExpensify This is how it will look:

Scan-expense-issue-recording.mp4

Let me know if that sound good to go, then I can push these commits and PR will move forward.

Note: This video is recorded in development server as I have these local changes.

cc: @suneox

@mountiny

mountiny commented Feb 2, 2026

Copy link
Copy Markdown
Contributor

Looks ok to me, @trjExpensify can you also confirm?

@trjExpensify
trjExpensify self-requested a review February 2, 2026 12:17
@mountiny

mountiny commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

@suneox can you please review?

@suneox

suneox commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

@suneox can you please review?

Yes, I’ll take a look at this PR today

@suneox

suneox commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

@suhailpthaj After merging with the latest main, the changes in this PR still don’t match the expected behavior when submitting an expense directly without going through a report group. (at 1:20, 2:10)

CleanShot.2026-02-05.at.23.44.28_.mp4

@suhailpthaj

suhailpthaj commented Feb 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @suneox I'll take a look at this on tomorrow.

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

@suneox Fixed the issue, you pointed out. Please have a look now.

@mountiny

mountiny commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

@suneox bump for a review

@suneox

suneox commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

@suneox bump for a review

Yes, I'll take a look at this one soon

@suneox

suneox commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
CleanShot.2026-02-09.at.19.41.57_.mp4
Android: mWeb Chrome
CleanShot.2026-02-09.at.19.43.45_.mp4
iOS: HybridApp
CleanShot.2026-02-09.at.19.33.39_.mp4
iOS: mWeb Safari
CleanShot.2026-02-09.at.19.24.50_.mp4
MacOS: Chrome / Safari
CleanShot.2026-02-09.at.19.18.47_.mp4

Fix

CleanShot.2026-02-09.at.19.22.44_.mp4
CleanShot.2026-02-09.at.19.48.13_.mp4

@suneox suneox left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The current change to update the logic for showing the preview message. LGTM

Before
CleanShot.2026-02-09.at.19.18.47_.mp4
After fix
CleanShot.2026-02-09.at.19.48.13_.mp4

@melvin-bot
melvin-bot Bot requested a review from mountiny February 9, 2026 13:00
Comment on lines 847 to 849
// If the last action differs from last original action, it means there's a hidden action (like a whisper), then use getLastVisibleMessage to get the preview text
if (!lastMessageTextFromReport && !lastReportAction && !!lastOriginalReportAction) {
if (!lastMessageTextFromReport && !lastReportAction && !!lastOriginalReportAction && isWhisperAction(lastOriginalReportAction)) {
return lastVisibleMessage?.lastMessageText ?? '';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@suneox @suhailpthaj What about this comment? What about other cases of hidden report actions that are not whisper - canUserPerformWriteAction is false

Comment on lines +857 to +868
if (reportID && !lastMessageTextFromReport && reportUtilsIsMoneyRequestReport(report)) {
const transactions = getReportTransactions(reportID);
const scanningTransactions = transactions.filter((transaction) => isScanning(transaction));

if (scanningTransactions.length > 0) {
lastMessageTextFromReport = translate('iou.receiptScanning', {count: scanningTransactions.length});
} else if (report?.transactionCount && report?.transactionCount > 0 && report?.currency) {
lastMessageTextFromReport = lastVisibleMessage?.lastMessageText;
} else if (report?.transactionCount === 0) {
lastMessageTextFromReport = translate('report.noActivityYet');
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you make sure to cover all of this with unit tests? also you can add unit tests for the ACTIONABLE_CARD_FRAUD_ALERT that has canUserPerformWriteAction as false

@suhailpthaj

suhailpthaj commented Feb 10, 2026

Copy link
Copy Markdown
Contributor Author

@mountiny Added the unit tests, reverted the changes in whisper logic.

Should we still add the test case "ACTIONABLE_CARD_FRAUD_ALERT that has canUserPerformWriteAction -> false".

Looking into the failing tests...

@mountiny

Copy link
Copy Markdown
Contributor

Yeah please if that test does not exist please add it

@suhailpthaj

Copy link
Copy Markdown
Contributor Author

@mountiny Added the test case for ACTIONABLE_CARD_FRAUD_ALERT.

@mountiny mountiny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks

@mountiny
mountiny merged commit a8ea5fe into Expensify:main Feb 11, 2026
29 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

Copy link
Copy Markdown
Contributor

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/mountiny in version: 9.3.18-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/lakchote in version: 9.3.18-8 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

if (scanningTransactions.length > 0) {
lastMessageTextFromReport = translate('iou.receiptScanning', {count: scanningTransactions.length});
} else if (report?.transactionCount && report?.transactionCount > 0 && report?.currency) {
lastMessageTextFromReport = lastVisibleMessage?.lastMessageText;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Directly using lastVisibleMessage?.lastMessageText as the LHN preview for expense reports here caused LHN - Expense amount is shown in bracket in LHN preview.
This text comes from the backend, which formats negative amounts with accounting-style parentheses (e.g., ($25.00)).
We customized this text in frontend from stable expense data like amount, currency, and comment in #86904 instead of relying on a raw message string that can be rehydrated differently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants