Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[$250] Hybrid - Android - Expense - On holding&unholding second expense in workspace chat, reports page crashes. #54561

Open
1 of 8 tasks
IuliiaHerets opened this issue Dec 25, 2024 · 11 comments
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Monthly KSv2 Reviewing Has a PR in review

Comments

@IuliiaHerets
Copy link

IuliiaHerets commented Dec 25, 2024

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.0.78-2
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: No
Issue reported by: Applause Internal Team
Device used: Redmi note 10s Android 13
App Component: Money Requests

Action Performed:

  1. Launch app
  2. Login with any account
  3. Go to workspace settings - workspace chat
  4. Create an expense
  5. Open the expense - header - hold the expense and unhold the expense
  6. Navigate to LHN-- reports
  7. Note reports page open correctly
  8. Open workspace chat
  9. Create another expense
  10. Open second expense - hold and unhold the expense
  11. Navigate to LHN -- reports

Expected Result:

On holding&unholding second expense in workspace chat, reports page must not crash.

Actual Result:

On holding&unholding second expense in workspace chat, reports page crashes.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6701999_1735113811053!Crash.txt

Bug6701999_1735113811053.Screenrecorder-2024-12-25-13-24-59-276_compress_1.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021871960620990473805
  • Upwork Job ID: 1871960620990473805
  • Last Price Increase: 2024-12-25
Issue OwnerCurrent Issue Owner: @Ollyws
@IuliiaHerets IuliiaHerets added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Dec 25, 2024
Copy link

melvin-bot bot commented Dec 25, 2024

Triggered auto assignment to @bfitzexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@promorthy
Copy link

Proposal

Please re-state the problem that we are trying to solve in this issue.

Hybrid - Android - Expense - On holding&unholding second expense in workspace chat, reports page crashes

What is the root cause of that problem?

Here we are not safely calling every on transactions using ? when item.transactions is undefined for isSelected

transactions: item.transactions?.map((transaction) => mapToTransactionItemWithSelectionInfo(transaction, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)),
isSelected: item.transactions.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),

What changes do you think we should make in order to solve the problem?

We should call every using optional chaining as we are doing for transactions prop

isSelected: item.transactions?.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple)

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

What alternative solutions did you explore? (Optional)

@bfitzexpensify bfitzexpensify added the External Added to denote the issue can be worked on by a contributor label Dec 25, 2024
Copy link

melvin-bot bot commented Dec 25, 2024

Job added to Upwork: https://www.upwork.com/jobs/~021871960620990473805

@melvin-bot melvin-bot bot changed the title Hybrid - Android - Expense - On holding&unholding second expense in workspace chat, reports page crashes. [$250] Hybrid - Android - Expense - On holding&unholding second expense in workspace chat, reports page crashes. Dec 25, 2024
@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Dec 25, 2024
Copy link

melvin-bot bot commented Dec 25, 2024

Triggered auto assignment to Contributor-plus team member for initial proposal review - @Ollyws (External)

@bfitzexpensify bfitzexpensify moved this to Bugs and Follow Up Issues in [#whatsnext] #expense Dec 25, 2024
@nkdengineer
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

On holding&unholding second expense in workspace chat, reports page crashes.

What is the root cause of that problem?

Item.transactions can be undefined but it's required in ReportListItemType type

transactions: TransactionListItemType[];

Then the app crashes here and no ts error.

isSelected: item.transactions.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),

Screenshot 2024-12-26 at 16 08 53

What changes do you think we should make in order to solve the problem?

We should change transactions here to optional and then fix all errors that use .transactions without optional chaining

transactions: TransactionListItemType[]; 

transactions: TransactionListItemType[];

Note: if we only fix optional chaining here without update ReportListItemType and fix all instances, the app still crashes

isSelected: item.transactions.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@bernhardoj
Copy link
Contributor

bernhardoj commented Dec 26, 2024

Proposal

Please re-state the problem that we are trying to solve in this issue.

After upholding an expense, opening a search page will crash.

What is the root cause of that problem?

The crash happens because the item here doesn't have the transactions property and if we check it, the item only has canHold and canUnhold.

: {
...item,
shouldAnimateInHighlight,
transactions: item.transactions?.map((transaction) => mapToTransactionItemWithSelectionInfo(transaction, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)),
isSelected: item.transactions.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),
};
}

Why? When we unhold the request, we will optimistically update the search snapshot data by merging the canHold and canUnhold data. It's supposed to be updated only when we do it from the search report RHP.

App/src/libs/actions/IOU.ts

Lines 8450 to 8463 in 918488a

// If we are unholding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync
if (searchHash) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`,
value: {
data: {
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: {
canHold: true,
canUnhold: false,
},
},
} as Record<string, Record<string, Partial<SearchTransaction>>>,
});

But in our case, even when doing it from the normal report screen, the snapshot is still updated and because the 2nd transaction that we unhold is never loaded on the search snapshot yet, the item only contains canHold and canUnhold properties.

Btw, even if the expense/transaction is loaded, it won't have transactions property either. It's only available if it's a REPORT type. That's why we "check the type" first here.

return SearchUIUtils.isTransactionListItemType(item)
? mapToTransactionItemWithSelectionInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)
: {
...item,
shouldAnimateInHighlight,
transactions: item.transactions?.map((transaction) => mapToTransactionItemWithSelectionInfo(transaction, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)),
isSelected: item.transactions.every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),
};

When we press the unhold, the function we already check first whether the topmost central pane is search page or not. If it's not, we won't pass the currentSearchHash (from the search context).

if (topmostCentralPaneRoute?.name !== SCREENS.SEARCH.CENTRAL_PANE && isTextHold) {
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.REPORT_WITH_ID.getRoute(targetedReportID));
return;
}
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute({reportID: targetedReportID}), currentSearchHash);

But we only do it if we are doing a HOLD. So, if it's unhold, we always pass the search hash.

What changes do you think we should make in order to solve the problem?

To solve this, we need to remove isTextHold from here so it's applied for both hold and unhold.

if (topmostCentralPaneRoute?.name !== SCREENS.SEARCH.CENTRAL_PANE && isTextHold) {
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.REPORT_WITH_ID.getRoute(targetedReportID));
return;
}

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

We can test PromotedActionsBar.hold directly and test 2 cases, 1 when the topmost central pane is a search report RHP and 1 when the topmost central pane is a search report central pane.

What alternative solutions did you explore? (Optional)

We can probably merge all the transaction data, but it's not preferable since they have different kinds of data too, such as action.

App/src/libs/actions/IOU.ts

Lines 8450 to 8463 in 918488a

// If we are unholding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync
if (searchHash) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`,
value: {
data: {
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: {
canHold: true,
canUnhold: false,
},
},
} as Record<string, Record<string, Partial<SearchTransaction>>>,
});

Or don't update the snapshot if the transaction data isn't available inside the snapshot yet.

Copy link

melvin-bot bot commented Dec 31, 2024

@Ollyws, @bfitzexpensify Eep! 4 days overdue now. Issues have feelings too...

@melvin-bot melvin-bot bot added the Overdue label Dec 31, 2024
@Ollyws
Copy link
Contributor

Ollyws commented Dec 31, 2024

Seems like @bernhardoj got the correct RCA here and their solution LGTM.
🎀👀🎀 C+ reviewed

Copy link

melvin-bot bot commented Dec 31, 2024

Triggered auto assignment to @marcaaron, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Dec 31, 2024
@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 labels Jan 1, 2025
@bernhardoj
Copy link
Contributor

PR is ready

cc: @Ollyws

@melvin-bot melvin-bot bot added Monthly KSv2 and removed Weekly KSv2 labels Jan 24, 2025
Copy link

melvin-bot bot commented Jan 24, 2025

This issue has not been updated in over 15 days. @Ollyws, @marcaaron, @bfitzexpensify, @bernhardoj eroding to Monthly issue.

P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Monthly KSv2 Reviewing Has a PR in review
Projects
Status: Bugs and Follow Up Issues
Development

No branches or pull requests

7 participants