Repository navigation
Upgrade react-native-vision-camera from v4 to v5 - #102898
AndrewGable merged 24 commits into
Conversation
|
|
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.
|
|
@codex review |
|
@MelvinBot review |
Code reviewThe migration looks solid. I found one bug worth fixing before merge, plus a few smaller items. I checked the v5.2.3 source to confirm several assumptions in the PR, and they hold:
1. Snapshot capture can lock the shutter (Android)In v5,
Fix: start the chain inside a promise so sync throws become rejections. For example: 2. Smaller items
I didn't run a web test. All of the changed camera code is native-only. |
|
@MelvinBot review |
Code review (re-review after c685779)The fixes from my last review work. I found no new bugs in the camera code. The one failing Jest suite is not caused by this PR. Fixed since last review
Failing check:
|
…n-camera-v5-102514 # Conflicts: # src/pages/iou/request/step/IOURequestStepScan/components/Camera/index.native.tsx # src/pages/iou/request/step/IOURequestStepScan/components/CameraViewport.tsx
# Conflicts: # ios/Podfile.lock
# Conflicts: # src/components/AttachmentPicker/AttachmentCamera.tsx # tests/ui/components/AttachmentCameraTest.tsx
d39db50 to
d68e148
Compare
|
@MelvinBot review |
Code review (re-review after fe9d6ee)The three new commits look good, and all CI checks pass except the approval gate. I found two small risks in the new code, both edge cases. Neither blocks the merge. 1. Android rotation fallback is always 90° now
Suggestion: v5's 2. iOS: the shutter works while the preview is hiddenWhile
Suggestion, if you think it's worth it: ignore shutter taps on iOS until the preview is live. You could also reveal the view only after What I verified
Still open
|
I moved the blink to |
|
Addressed the latest feedback:
|
Those are interesting findings, would be great if anyone can find fixes and submit PRs to react-native-vision-camera for me to review and potentially upstream :) |
@mrousavy Already did, check this comment: #102514 (comment) |
|
@situchan Can you take a final look at the latest changes? |
|
Were you able to reproduce Melvin's regressions? |
|
Please check this one: [iOS] Screen auto-locks while a camera is openv4 kept the screen awake while the camera was active (
Expected: Screen stays on, as on main. |
|
Confirmed. This is a real iOS regression in this PR. Android is not affected, because v4 never kept the screen on there either. Root cause: v4's iOS Recommended fix: Add a fourth v5.2.3 patch to Evidence
I verified this by reading the code only. I didn't run it on an iOS device. |
We changed that elsewhere to also improve performance. Asking about it earlier |
I couldn’t reproduce it earlier, but my test setup kept the phone awake everywhere. I added a VisionCamera patch that sets |
@situchan Yes, and they’re fixed. Most were on the VisionCamera side, so I opened PR's there and added them as patches here until they’re released. |
|
Looks good but let's run final adhoc build @AndrewGable |
|
🚧 AndrewGable has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
# Conflicts: # ios/Podfile.lock
Final review (from scratch, at f4e6e8e)I found no new regressions that block the merge. CI is green. All four VisionCamera patches are applied, and I found no crash, deadlock or restart loop in them. Two risks we discussed before are still open by choice. I also found three small issues. Still open (you chose to accept these)
New, minor
Low-risk notes and what I checkedLow-risk notes
Checked and fine
I reviewed the native code by reading it. I didn't test on an iOS or Android device. view run · no recording available |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 AndrewGable 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/AndrewGable in version: 9.5.20-0 🚀
|
|
No help site update needed. This PR upgrades the camera library and keeps the Scan, attachment and odometer camera flows the same for users, so no sentence in |
|
🚀 Deployed to production by https://github.com/jasperhuangg in version: 9.5.20-5 🚀
Bundle Size Analysis (Sentry): |



Explanation of Change
Upgrades
react-native-vision-camerafrom^4.7.2to5.2.3and adds its required peerreact-native-nitro-image0.15.2. V5 rewrote the camera session code that the patch fixed, so this PR removes the patch (patches/react-native-vision-camera/) and the disableFrameProcessors flag.**The receipt scan, attachment and odometer cameras all move to the V5 API.
Capture
qualityPrioritization: 'speed', and we prepare the photo settings after every configure, as recommended. This also fixes the low iOS receipt quality ([Due for payment 2026-10-20] SmartScan captures lower-quality images than the native iOS Camera app #99615): receipts are 2592×1944 photos now, not 1440×1920 video frames, and a capture takes about 75 to 100 ms (V4 snapshot p50: 60 ms).src/libs/cameraCapture, saves photos as JPEG (V5 defaults to HEIC on iOS) straight into the receipts folder and disposes the in-memory photo after the write.Camera setup
currentResolution) once configured.neutralZoom, which V5 dropped). We pick the wide and ultra-wide device ourselves, because V5'sphysicalDevicesfilter can't rank it.zoomunset when it would be 1. Setting it hits a V5 race on Android where CameraX rejects the zoom with "Camera is not active".onPreviewStartedand restart the camera on the ultra-wide lens until then. A close receipt is sharp right away; before, iOS took about a second to switch to the macro lens.focusTowith explicit modes. We no longer log focus requests that a newer tap cancelled.fromNitro, so a synchronous throw (for exampletakeSnapshotbefore the preview attaches) reaches the error handling and no longer locks the shutter.Telemetry and logging
onConfigured(the point V4 reported asonInitialized) and reports the session's autofocus system (iOS only), the lens count and the wide-lens zoom. V5 doesn't expose V4's format list, so we removed the three attributes built on it.While testing I found an Android bug that main has too: leaving Scan during a flash capture shows a "Camera error" alert on the next screen. fixes it separately.
Fixed Issues
$ #102514
PROPOSAL:
Tests
Receipt scan
Attachment camera
14. In any chat, tap + > Take photo.
15. Verify the back camera opens at 1x. Capture and verify the attachment preview is upright.
16. Flip to the front camera and capture again.
17. Close the camera while a capture is in progress and verify nothing breaks.
Odometer
18. Create a distance expense with the odometer option and take the start photo.
19. Verify the cropped photo is upright and saved.
20. Go back to the odometer camera and verify the viewfinder is sharp, with no frozen old frame.
Camera teardown (the dropped iOS patch)
21. Open Scan and leave the screen right away. Repeat a few times.
22. Tap the shutter and leave the screen during the capture. Repeat a few times.
23. Tap the shutter and leave the confirmation page immediately. Repeat a few times.
24. Verify the app doesn't hang or crash, and the camera works when you come back.
Other
25. Background the app while on Scan and return. Verify the camera resumes.
26. Deny camera permission and open Scan. Verify the permission prompt shows.
Offline tests
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
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
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari