Repository navigation
Use useDecisionModal for Search bulk actions and SelectionToolbar alerts - #103554
Conversation
Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
|
🤖 Web test steps verification results: The offline and empty-report "Download failed" alerts work on web in Search bulk actions and the report selection toolbar, including the selection-toolbar Export that froze on Android. I could not test closing an alert with the browser Back button because the web test tool can't press Back. The PR's Tests section is still a TODO, so I derived these steps from the PR description.
|
|
@MelvinBot |
|
I updated the PR description. It now has Tests, Offline tests, and QA steps, plus the web and Android screenshots and recordings from my earlier test runs on commit Still open before this is ready for review:
What I checked and why
|
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-10-14.at.11.31.37.movScreen.Recording.2026-10-14.at.11.32.13.movScreen.Recording.2026-10-14.at.11.32.51.movAndroid: mWeb ChromeScreen.Recording.2026-10-14.at.11.31.37.movScreen.Recording.2026-10-14.at.11.32.13.movScreen.Recording.2026-10-14.at.11.32.51.moviOS: HybridAppScreen.Recording.2026-10-14.at.11.43.53.movUploading Screen Recording 2026-10-14 at 11.44.44.mov… iOS: mWeb SafariScreen.Recording.2026-10-14.at.11.25.09.movScreen.Recording.2026-10-14.at.11.25.41.movScreen.Recording.2026-10-14.at.11.26.24.movMacOS: Chrome / SafariScreen.Recording.2026-10-14.at.11.20.58.movScreen.Recording.2026-10-14.at.11.21.05.movScreen.Recording.2026-10-14.at.11.21.14.movScreen.Recording.2026-10-14.at.11.21.28.movScreen.Recording.2026-10-14.at.11.21.48.movScreen.Recording.2026-10-14.at.11.22.07.mov |
|
@MelvinBot |
Keep main's removal of the offline guard on bulk Remove hold, and update the new offline unhold test to assert via the useDecisionModal mock. Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
|
I fixed the conflicts by merging
I couldn't run Jest, lint, or typecheck locally. They fail at startup in my environment, including on unrelated test suites. CI will run them on the new commit. |
|
The failing check is unrelated to this PR, so I didn't push a fix. Analysis: Evidence:
|
|
Nothing has changed since my earlier comment. The failing check is still unrelated to this PR, so I didn't push a fix. Analysis: Evidence:
Next step: Re-run the failed |
|
@MelvinBot |
|
I marked this PR as ready for review. |
|
@ZhenjaHorbach 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] |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a77a7dca94
ℹ️ 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".
| const {showDecisionModal} = useDecisionModal(); | ||
|
|
||
| const showOfflineModal = () => { | ||
| showDecisionModal({ |
There was a problem hiding this comment.
Delay the global alert until the export popover closes
On Android, when an offline user selects an export option from the report selection toolbar, this synchronously presents the global native modal before ButtonWithDropdownMenu finishes dismissing its popover. The overlapping modals leave the alert stuck: neither “Got it” nor hardware Back responds, and the report remains blocked. Present this alert from the popover's post-dismiss callback or otherwise defer it until the originating menu has fully closed.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
@MelvinBot
Can't reproduce
But makes sense, and we can add these changes just in case
diff --git a/src/hooks/useSelectedTransactionsActions.ts b/src/hooks/useSelectedTransactionsActions.ts
index bd88e40df03f40..904ab27f5107ca 100644
--- a/src/hooks/useSelectedTransactionsActions.ts
+++ b/src/hooks/useSelectedTransactionsActions.ts
@@ -466,6 +466,7 @@ function useSelectedTransactionsActions({
clearSelectedTransactions(true);
}
: () => beginExportWithTemplate(template.templateName, template.type, selectedTransactionIDs, template.name, template.policyID),
+ shouldCallAfterModalHide: true,
addSeparatorBefore,
};
};
|
Nothing has changed since my last check. The only real failure is still a flaky test that this PR doesn't touch, so there's no code to fix. Please re-run Evidence:
|
|
@MelvinBot |
Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
|
I added |
|
@roryabraham 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] |
|
Nothing has changed since my last comment. The only real failure is still the flaky What you need to do: Re-run the failed Why it's unrelated:
|
|
This change is already on the PR, so I didn't add a new commit. Commit 931c484 ("Run export template actions after the popover menu hides") adds |
|
TS issue is not from this PR |
|
ts issue is unrelated |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 roryabraham has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.5.10-0 🚀
|
|
No help site update needed. This PR moves existing offline and "Download failed" alerts to the shared decision modal, which only changes how in-app error messages are shown, so no help article becomes incorrect. |
|
🚀 Deployed to staging by https://github.com/roryabraham in version: 9.5.12-0 🚀
|
|
No help site update needed. This PR moves existing offline and "Download failed" alerts to the shared decision modal, which only changes how in-app error messages are shown, so no help article becomes incorrect. |
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.5.12-1 🚀
Bundle Size Analysis (Sentry): |








Explanation of Change
Batch 2 of the
DecisionModal→useDecisionModalmigration. Search bulk actions and the reportSelectionToolbareach mounted their own one-buttonDecisionModalalerts and kept visibility state for them. These five alerts now open through the globaluseDecisionModal():useSearchBulkActions/SearchBulkActionsButton):showOfflineModal(). ThedeferModalPresentationAfterPopoverDismisswrapper in bulk pay is kept, so iOS still waits for the popover to close.downloadFailedEmptyReportDescriptionwith the count. All other failures usedownloadFailedDescription. Before, the prompt read a sharedemptyReportsCountthat was reset in only one place. A later, unrelated failure could show the stale "empty report" text.exportExpensifyCardStatementPDF.onExportFailed. This also fixes a bug. On wide layouts the toolbar unmounts after a CSV export starts, so the inline modal never appeared when the export failed. The global modal does not depend on the toolbar staying mounted.MoneyReportHeaderModals.Removed the old visibility state, close handlers,
emptyReportsCount, and the related return fields.SearchBulkActionsButton.tsxno longer importsDecisionModal. TheProcessMoneyReportHoldMenublock inSelectionToolbaris left for Batch 3.Behavior notes:
shouldHandleNavigationBackis nowtrue, so browser Back closes these alerts.Tests: the bulk-action hook tests now mock
useDecisionModal(asuseExportActionsTestdoes) and assert the title and prompt shown. A new test covers the empty-report prompt.AI Tests (run by MelvinBot):
npm run typecheck: passedno-unsafe-type-assertionerrors already exist onmain.oxfmtandnpm run spell-changed: cleanSearchBulkActionsButtonandSelectionToolbarcompile.useSearchBulkActionsfails with the same errors onmain(refs accessed during render), so this PR doesn't regress it.useSearchBulkActionsPayTest,useSearchBulkActionsDownloadReceiptsTest,useSearchBulkActionsDownloadPDFTest,useSearchBulkActionsExportTest, andSearchBulkActionsButtonTestpassed (114 tests). The full Jest suite and Storybook smoke test were not run locally.Fixed Issues
$ #102976
PROPOSAL:
Tests
Offline tests
QA Steps
Same as Tests, on staging. For the offline steps, use Force offline in Account > Troubleshoot or turn off the device network.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Tested by MelvinBot on an Android emulator (standalone NewDot) at commit 0a22005. Recording · Run
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Tested by MelvinBot on web (Chrome, dev build) at commit 0a22005. Recording · Run
Every alert showed the right text and closed with "Got it". Tests step 5 (browser Back) was not tested because the test tool can't press Back.