[Odometer] Redirecting to inbox on photo capture after App reload on OdometerImage screen#83668
Conversation
…nbox_deploy_blocker
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.
|
…nbox_deploy_blocker
…tion to fix back navigation
…nbox_deploy_blocker
…nbox_deploy_blocker
|
@DylanDylann 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] |
Julesssss
left a comment
There was a problem hiding this comment.
I think if user replaces images we're no longer clearing it. Maybe we can do that before we set odometerStartImage to a new blob?
|
🚧 @Julesssss has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
Oh great, thanks for pointing that out. |
|
In that case I think we're ready for @DylanDylann's review now |
…vent TS2590 union type complexity errors
|
I need more time to complete my review. I will try to complete it before the new week |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 09eb6c7862
ℹ️ 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".
src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx
Outdated
Show resolved
Hide resolved
… with isEditingConfirmation param
…meter image screen
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
|
🚧 @Julesssss has triggered a test Expensify/App build. You can view the workflow run here. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-03-10.at.01.20.50.movAndroid: mWeb ChromeScreen.Recording.2026-03-10.at.01.15.23.moviOS: HybridAppiOS: mWeb SafariScreen.Recording.2026-03-10.at.01.14.43.movMacOS: Chrome / SafariScreen.Recording.2026-03-10.at.01.13.38.mov |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
Julesssss
left a comment
There was a problem hiding this comment.
Testing well. I just noticed that the 'replace' button is cutoff but that's a separate issue
|
🚧 @Julesssss 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/Julesssss in version: 9.3.34-0 🚀
|
|
Sorry I didn't get to this in time! All looks good for product. |
|
🚀 Deployed to production by https://github.com/luacmartins in version: 9.3.34-2 🚀
|
Explanation of Change
After capturing an odometer photo, the user was being redirected to the wrong screen - to Inbox on native after app reload, or back to the Odometer creation tab instead of the Confirmation screen on web.
The bug affects both native and web, and manifests in two distinct ways depending on the platform and entry point:
Native (reported deploy blocker):
Navigation.goBack()inIOURequestStepOdometerImagehad no fallback route. Before app reload, this works fine because the previous screen is on the navigation stack. After reload (e.g. after granting camera permissions via Settings and returning), the stack is gone andgoBack()falls through to Inbox.Web (variation of the same bug): The back navigation route was always hardcoded to
DISTANCE_REQUEST_CREATE_TAB_ODOMETERregardless of where the user came from. So when the flow wasConfirmation screen -> Edit odometer image -> Replace/take photo, the user was brought back to the Odometer creation tab instead of back to the Confirmation screen.Additionally, a single
MONEY_REQUEST_RECEIPT_PREVIEWroute was shared between regular receipt preview and odometer image preview. This meant when we navigated toODOMETER_IMAGEthrough "Replace" button in the odometer image preview we couldn't distinguish whether it was opened from the creation flow or from the confirmation screen.This PR is a blocker for image stitching feature testing - it's impossible to verify that images are properly stitched when the "Replace" flow from the confirmation screen navigates to the wrong destination.
Changes made:
Explicit back navigation in
IOURequestStepOdometerImage: Instead ofNavigation.goBack()(which relies on stack presence),navigateBacknow callsNavigation.goBack(goBackRoute)with an explicit target - eitherMONEY_REQUEST_STEP_DISTANCE_ODOMETER(when editing from confirmation) orDISTANCE_REQUEST_CREATE_TAB_ODOMETER(normal creation flow).Pass context through route params:
ODOMETER_IMAGEroute now carriesisEditingConfirmationso that the camera screen always knows where to navigate back to, regardless of app reload state.Separate routes for odometer image previews: Added new route (
MONEY_REQUEST_ODOMETER_PREVIEWwithisEditingConfirmation) instead of reusingMONEY_REQUEST_RECEIPT_PREVIEW. This allows us to properly passisEditingConfirmationtoODOMETER_IMAGEto correctly determine whether to navigate back to the creation flow or the confirmation screen.Transaction.tstype fix: CorrectedodometerStartImage/odometerEndImagetypes fromFile | stringtoFileObject | stringto match the actua values used on web (aFileObjectwith a.uriproperty is stored, not a rawFile).Removed premature blob URL cleanup: The
useEffectcleanup calls inIOURequestStepDistanceOdometerthat revoked blob URLs on component unmount were removed (they caused the image to become inaccessible when navigating to the odometer screen from confirmation plus they are redundant).Fixed Issues
$ #83526
PROPOSAL: N/A
Tests
On mobile:
Caution
Use an Android emulator or physical iOS device for testing - the iOS simulator doesn't support camera functionality.
Prerequisites: Disable camera permissions for Expensify (set to "Ask every time").
Main bug fix (the deploy blocker):
FAB->Track distance->OdometertabStart readingthumbnailContinue-> when prompted, pressDon't allowContinueagain -> when prompted with the Settings redirect dialog, pressSettingsTip
Instead of doing steps 3-6 you can simply grant access to the camera and reload the App -> it's actually the reload of the App after we come back from Settings that is the problematic part not the camera permissions itself
Back navigation - creation flow:
Continue-> grant camera permission -> take a photoReplace-> verify you are brought to the odometer image screenBack navigation - confirmation/edit flow:
Replace-> verify you are brought to the odometer image screen and after taking a photo you land back on the distance screenOn web:
FAB->Track distance->OdometertabStart readingthumbnailBack navigation - creation flow:
Replace-> verify you are brought to the odometer image screenBack navigation - confirmation/edit flow:
Replace-> verify you are brought to the odometer image screen and after taking a photo you land back on the distance screenOffline tests
Same as Tests
QA Steps
Same as Tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))\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.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
iOS needs to be tested on a physcical device
Android: Native
Steps 1 through 7:
androidnative1to7.webm
Steps 8 through 12:
androidnative8to12.webm
Steps 13 through 18:
androidnative13to18.webm
Android: mWeb Chrome
Steps 1 through 7:
androidweb1to7.webm
Steps 8 through 12:
androidweb8to12.webm
Steps 13 through 18:
androidweb13to18.webm
MacOS: Chrome / Safari
Steps 1 through 5:
web1to5.mov
Steps 6 through 10:
web6to10.mov
Steps 11 through 16:
werb11to16.mov