Skip to content

[CP Staging] Fix pre-mount teardown under Share modal and offline not-found flash for pending reports - #100826

Merged
mountiny merged 5 commits into
Expensify:mainfrom
software-mansion-labs:korytko/fix-premount-deploy-blockers
Sep 10, 2026
Merged

mountiny merged 5 commits into
Expensify:mainfrom
software-mansion-labs:korytko/fix-premount-deploy-blockers

Conversation

@JakubKorytko

Copy link
Copy Markdown
Member

Explanation of Change

Fixes two regressions from #97874:

  1. Pre-mount teardown only recognized RIGHT_MODAL_NAVIGATOR, while insert also accepted SHARE_MODAL_NAVIGATOR. Backing out of the Share > Submit confirm page left a stale buffer and tab route that later overwrote the Share destination. Added isPreMountBufferHostName and used it in preMountBuffer.ts and handleRemoveFullscreenUnderRHP.
  2. ReportNotFoundGuard ignored the isPendingCreation route param, so offline the pre-mounted destination flashed "Not here" before the optimistic report landed. The guard now suppresses not-found while the param is set.

Fixed Issues

$ #100767
$ #100785
PROPOSAL: N/A

Tests

Test 1 (#100767): Native share - wrong destination after backing out of the Submit tab (Android and iOS native only)

  1. Sign in, then background the app.
  2. Open a photo in the device gallery and share it to Expensify.
  3. On the Submit tab, select your self DM. The confirm page opens.
  4. Tap the app back button on the confirm page.
  5. Switch to the Share tab.
  6. Select a different user.
  7. Tap Share.
  8. Verify that the chat with the user from step 6 opens and shows the shared photo. Verify that the self DM from step 3 does not open.

Test 2 (#100785): "Not here" flash when submitting to a new contact offline (narrow layout)

  1. Use an account with no existing chat with the recipient.
  2. FAB > Create expense > Manual, select that recipient, enter an amount, reach the confirm page.
  3. Go offline (Settings > Troubleshoot > Force offline, or disable the network).
  4. Tap Create expense.
  5. Verify that the new chat opens with the pending expense and the "Not here" page never appears.
  6. Go back online.
  7. Verify that the expense syncs and the chat stays on screen.

Offline tests

Covered by Test 2 above

QA Steps

Same as tests

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 followed proper code patterns (see Reviewing the code)
    • 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 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)
  • 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)
  • 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.
  • 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.mov
Android: mWeb Chrome
iOS: Native
iOS.mov
iOS: mWeb Safari
MacOS: Chrome / Safari

@JakubKorytko

Copy link
Copy Markdown
Member Author

@codex review

@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: 364f8dcde6

ℹ️ 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 thread src/pages/inbox/ReportNotFoundGuard.tsx Resolved
@JakubKorytko

Copy link
Copy Markdown
Member Author

@codex review

@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: 9b4cd7f89a

ℹ️ 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 thread src/pages/inbox/ReportNotFoundGuard.tsx Resolved
@JakubKorytko

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 2c5be81b23

ℹ️ 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".

@JakubKorytko

Copy link
Copy Markdown
Member Author

@MelvinBot review

@MelvinBot

MelvinBot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Code review — the direction of both fixes is right, but I found 3 issues worth addressing before merge, plus 2 nits.

The asymmetry diagnosis in the PR body is correct and confirmed against main: captureBufferTransaction already accepted SHARE_MODAL_NAVIGATOR, while removePreInsertedFullscreenIfNeeded and handleRemoveFullscreenUnderRHP bailed on anything that wasn't the RHP — so the buffer was recorded under Share and then never torn down. That is exactly the #100767 symptom, and the helper's membership ({RHP, Share}) is the right set.


1. 🔴 isPendingCreation is honored on a route where it can never expire

ReportNotFoundGuard.tsx:59 reads the param with no route.name check. But ReportFetchHandler.tsx:95 gates it on route.name === SCREENS.REPORT, and both clearing effects derive from that value (:351, :361).

ReportScreen serves two screens — SCREENS.REPORT and SCREENS.RIGHT_MODAL.SEARCH_REPORT via RHPReportScreen.tsx:14-21. So on /search/view/<id>?isPendingCreation=true the guard suppresses not-found, neither clearing effect ever runs, and the screen sits on a permanent skeleton with no recovery path.

Fix: gate the guard's read on route.name === SCREENS.REPORT — or better, drop the as cast and use the typed union like the three siblings in the same folder (ReportFetchHandler.tsx:65-67, ReportRouteParamHandler.tsx:19-21, ReportNavigateAwayHandler.tsx:33-35). RightModalNavigatorParamList[SEARCH_REPORT] has no isPendingCreation, so TS would have rejected this read on its own. The cast is what hid it.

2. 🟡 The expiry owner isn't guaranteed to be mounted

ReportScreen.tsx:126 renders ReportFetchHandler only when !shouldDeferNonEssentials, while ReportNotFoundGuard at :130 renders unconditionally. The guard can therefore honor the flag with its only expiry owner unmounted. Bounded in practice by useDeferNonEssentials' 3s safety timeout — but that lift lives inside a useFocusEffect, so a deferred-but-never-focused screen keeps it unmounted indefinitely.

3. 🟡 The 5s expiry can reproduce the exact flash it's meant to prevent

The stale-flag timeout is the change that isn't in the PR description and isn't covered by Test 2. Two concerns:

It's reachable in the normal flow. The optimistic report is written after navigation, not before — submitWithDismissFirst.ts:83-89 dispatches dismissModal immediately and only runs executeWrite in afterTransition. So the pre-inserted screen gains focus first, and the write races a ~2s transition budget (MAX_TRANSITION_START_WAIT_MS + MAX_TRANSITION_DURATION_MS). 5s leaves ~3s margin on a jank-prone path, not a guaranteed ordering.

The terminal state is worse than a delayed flash. Clearing the param re-triggers the fetch effect; the gate at ReportFetchHandler.tsx:183 is now false, so openReport fires for the client-generated ID — the 403 that gate's own comment exists to prevent. And offline, isLoading drops the isLoadingInitialReportActions term (ReportNotFoundGuard.tsx:55), so "Hmm… it's not here" renders immediately at t=5s. Offline is precisely the #100785 scenario.

Worth describing this change in the PR body, and adding isPendingCreation to the not-found Log.info payload so an expiry-caused not-found is distinguishable from a real 404 in production.


Two nits

Insert and teardown still don't actually agree on the host set. The new helper's own doc says "insert and teardown must agree on this set" (isNavigatorName.ts:51), but the insert gate at GetStateForActionHandlers.ts:509-512 is still !rhpRoute || isFullScreenName(rhpRoute.name) — it accepts any non-fullscreen top route, far broader than {RHP, Share}. That breadth is what allowed this bug to exist. Gating it on isPreMountBufferHostName (or at minimum a Log.hmmm on mismatch) makes the two sets structurally identical, so the next screen adopting usePreMountDestination under a different modal fails loudly instead of silently reproducing #100767.

canNativeSwipeDismissRHP's name and doc are now stale. Its inner-state probe assumes the RHP's nested shape; ShareModalStackNavigator is flat. Behavior is unchanged today only because SUBMIT_DETAILS renders no nested navigator. But ShareRootPage renders an OnyxTabNavigator, so if a pre-insert ever runs with SHARE.ROOT focused on the Submit tab, this returns false and skips the buffer — even though SHARE_MODAL_NAVIGATOR is gestureEnabled: true, i.e. exactly the unprotected-swipe hole the buffer exists to close. A comment or a Share-specific branch would keep that from creeping in later.

Things I checked and cleared
  • The === 'true' string compare is correct. The only writer is ROUTES.ts:2590-2592, which pushes a literal query-string segment; the value always arrives through getStateFromPath → queryString.parse with no parseBooleans, and the declared param type is isPendingCreation?: string. No boolean path exists. (Note this param list mixes conventions — openOnAdminRoom is a real boolean — so the string compare is safe rather than self-evident.)
  • isPreMountBufferHostName doesn't need more navigators. Every usePreMountDestination call site lives in MoneyRequestModalStackNavigator (RHP-only) or SubmitDetailsPage (Share-only). Adding TEST_TOOLS_MODAL_NAVIGATOR would be actively wrong — it replaces the top modal via handleNavigatingToModalFromModal, so teardown would restore the tab under it.
  • navigation.setParams on an unmounted route is safe — it's route-scoped via source: route.key (unlike the global Navigation.setParams), and the clearTimeout cleanup covers it regardless. The isFocused gate isn't needed for safety, though it's harmless.
  • isInvalidReportPath is correctly left unsuppressed, and the new test covers it.
  • The useNavigation identity is stable in production (per-route cache keyed by route.key), so the dep array doesn't restart the timer spuriously. One caveat: ReportFetchHandlerTest.tsx:27 mocks useNavigation to return a fresh object every render, so the new test only passes because nothing re-renders during advanceTimersByTime — it doesn't actually validate the stability it appears to.

I attempted to run Test 2 on web at a narrow viewport, but the browser session went blank right after the first drive command and never recovered — an environment failure on my side, not a signal about this PR. The review above is static analysis only, so the offline behavior still needs a human pass.


view run · view recording

@JakubKorytko

Copy link
Copy Markdown
Member Author

@MelvinBot I've Addressed 1 (route gated to SCREENS.REPORT), 3 (grace period now 15s, well past the 2s transition cap, and isPendingCreation added to the not-found log) and the canNativeSwipeDismissRHP comment. On 2: the deferral lifts on focus, and a never-focused screen is the pre-mounted case where we do not want expiry, so no change. Insert gate tightening is a fair follow-up but out of scope for a deploy blocker. Please re-review.

@MelvinBot

MelvinBot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Re-review of 83d4c7d — all three issues resolved. No blocking concerns left from my side.

# Issue Status
1 isPendingCreation honored where it can't expire ✅ Fixed
2 Expiry owner not guaranteed mounted ✅ Your reasoning is right — withdrawn
3 5s expiry could reproduce the flash ✅ Addressed
— Insert gate tightening 👍 Agreed, follow-up
— canNativeSwipeDismissRHP doc ✅ Comment added

1 — ReportNotFoundGuard.tsx:61 now matches ReportFetchHandler.tsx:95 exactly, so the /search/view/<id>?isPendingCreation=true permanent-skeleton path is closed.

2 — you're right, I'm withdrawing this one. I re-checked and the expiry effect is itself gated on isFocused (ReportFetchHandler.tsx:362), so "unmounted while unfocused" and "mounted while unfocused" are behaviorally identical — the timer doesn't run either way. And in the one window where the screen is focused but still deferred, the lift is bounded by useDeferNonEssentials' 3s safety timeout. Nothing unbounded. My original framing missed the isFocused gate.

3 — 15s against a ~2s transition cap is a comfortable margin, and the reasoning is now recorded in the comment.


Two small follow-ups, neither blocking

The new log field can't actually show true for the case it was added for. shouldShowNotFoundPage only reaches the isReportMissingAfterLoad branch when !isPendingCreation, and by the time the timer fires the param is already cleared — so on an expiry-caused not-found the field logs false. It's only ever true on the isInvalidReportPath branch. To distinguish an expiry-caused not-found from a real 404 you'd want to log the expiry event itself where the timeout fires, rather than the guard's current param value. Low value either way; just flagging that this field won't answer the question it was meant to.

No test covers the route gate. ReportNotFoundGuardTest.tsx:24 hardcodes name: 'Report', so the SEARCH_REPORT hole the gate closes is untested. The params mock is already a let — making name variable too is a couple of lines.

Verification performed

🤖 Web test steps verification results: ✅ pass

Creating an expense to a brand-new recipient while offline opens the new chat with the pending expense immediately, survives 22+ seconds offline without the not-found page ever appearing, and syncs cleanly once back online.

Chat with $42.00 expense synced online

Step Status
Online: FAB > Create expense > Manual, pick brand-new recipient, enter amount, reach the pre-submit stateRecipient selected, Amount=25 filled on the manual create-expense form before submission.
Manual expense form filled for a brand-new recipient
✅
Go offline via Settings > Troubleshoot > Force offlineForce offline toggled on and the app displayed the "You appear to be offline" banner.
Force offline toggle enabled in Troubleshoot settings
✅
Offline: create expense to a brand-new recipient, new chat opens with pending expense, no "not here" pageCreated a $42.00 cash expense offline; the new report loaded directly showing Outstanding $42.00 and the offline banner — no not-found page.
New offline chat showing pending $42.00 expense, no not-found page
✅
Staying on the chat, offline, for 20+ seconds does not trigger the not-found page (exercises the 15s grace period)Waited 22 seconds on the same report screen while still offline; identical pending-expense content, still no not-found page.
Same chat still showing pending expense after 22s offline
✅
Go back online; expense syncs and the chat stays on screenOffline banner disappeared; the $42.00 expense chat loaded normally online with no forced navigation away or not-found flash.
Force offline toggled off, offline banner gone
Chat with $42.00 expense synced online
✅

Caveat on what this proves: the web build's manual flow is a single-page form with no separate confirm page, so I can't confirm the run went through the same pre-mount code path that sets isPendingCreation on native. Treat this as evidence that the offline create-expense flow is healthy and un-regressed, not as a substitute for the native Test 1 and Test 2 runs — #100767 is Android/iOS share-intent only and is not reachable on web at all.


view run · no recording available

@JakubKorytko
JakubKorytko marked this pull request as ready for review September 10, 2026 12:58
@JakubKorytko
JakubKorytko requested review from a team as code owners September 10, 2026 12:58
@melvin-bot
melvin-bot Bot requested a review from marufsharifi September 10, 2026 12:59
@melvin-bot

melvin-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

@marufsharifi 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]

@melvin-bot
melvin-bot Bot requested review from trjExpensify and removed request for a team September 10, 2026 12:59
@trjExpensify

Copy link
Copy Markdown
Contributor

PR doesn’t need product input as a performance refactor PR. Unassigning and unsubscribing myself.

@trjExpensify
trjExpensify removed their request for review September 10, 2026 13:04
@mountiny
mountiny self-requested a review September 10, 2026 13:29
@mountiny mountiny changed the title Fix pre-mount teardown under Share modal and offline not-found flash for pending reports [CP Staging] Fix pre-mount teardown under Share modal and offline not-found flash for pending reports Sep 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

This comment has been minimized.

@marufsharifi

marufsharifi commented Sep 10, 2026 •

Copy link
Copy Markdown

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 proper code patterns were followed (see Reviewing the code)
    • 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 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)
  • 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)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • 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
    • 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 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.
  • 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
Screen.Recording.2026-09-10.at.9.29.37.PM.mp4
Android: mWeb Chrome
iOS: HybridApp
Screen.Recording.2026-09-10.at.8.11.21.PM.mov
iOS: mWeb Safari
MacOS: Chrome / Safari

@marufsharifi marufsharifi 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.

LGTM

@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.

That's for a quick work on this

@mountiny
mountiny merged commit 2547ac9 into Expensify:main Sep 10, 2026
36 of 38 checks passed
@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.

@github-actions

Copy link
Copy Markdown
Contributor

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

OSBotify pushed a commit that referenced this pull request Sep 10, 2026
…mount-deploy-blockers

(cherry picked from commit 2547ac9)

(cherry-picked to staging by mountiny)
@OSBotify OSBotify added the CP Staging marks PRs that have been CP'd to staging label Sep 10, 2026
@os-botify

os-botify Bot commented Sep 10, 2026

Copy link
Copy Markdown

🔁 Filed a Staging retest request for deploy blockers #100767, #100785 after this PR was cherry-picked to staging.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/mountiny in version: 9.4.75-3 🚀

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

@MelvinBot

MelvinBot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

🤖 No help site changes are required for this PR. No draft docs PR was created.

Why: This PR fixes two navigation regressions. Both restore the behavior the help site already describes — neither changes a documented feature, setting, label, or user-facing flow.

Review details

What changed (all internal):

File Change
src/libs/Navigation/helpers/isNavigatorName.ts New isPreMountBufferHostName helper so insert and teardown agree on the same navigator set
src/libs/Navigation/helpers/preMountBuffer.ts Teardown now also recognizes SHARE_MODAL_NAVIGATOR, not just RIGHT_MODAL_NAVIGATOR
src/pages/inbox/ReportNotFoundGuard.tsx Guard honors the isPendingCreation route param, so "Not here" no longer flashes offline
src/pages/inbox/ReportFetchHandler.tsx Expires a stale isPendingCreation flag after 15s
src/CONST/index.ts + 4 test files New timing constant and regression tests

Both fixes are corrections to broken behavior, not new behavior:

  1. Native share destination — Backing out of the Submit confirm page left a stale buffer that overwrote the Share destination. After the fix, sharing goes to the chat you picked. That is what any user would already expect; no article documents the wrong behavior.
  2. Offline "Not here" flash — A transient wrong screen appeared before the optimistic report landed. Removing a flash of an error page doesn't change anything documented.

Help site search: I searched docs/articles for native share, share sheet, "Not here", and offline behavior. The only matches were Travel-receipt-integrations.md and unrelated offline mentions (SmartScan troubleshooting, Spend page, Workspace workflows) — none describe the flows this PR touches.

No copy changes: The diff adds no user-facing strings and touches no src/languages/*.ts file, so there are no feature names, tab names, or button labels to verify against the live UI.

JakubKorytko — since no docs changes were needed, there's no linked help site PR to review or mark Ready for review. If you think a specific article should cover the native share flow or offline report creation more explicitly, reply with @MelvinBot and the article you have in mind and I'll draft it.


view run · no recording available

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.75-3 🚀

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

Bundle Size Analysis (Sentry):

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/mountiny in version: 9.4.76-0 🚀

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

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.75-3 🚀

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

Bundle Size Analysis (Sentry):

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.76-1 🚀

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

Bundle Size Analysis (Sentry):

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

Labels

CP Staging marks PRs that have been CP'd to staging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants