fix: use in-app VisionCamera for chat attachment photos (re-land)#96458
fix: use in-app VisionCamera for chat attachment photos (re-land)#96458MelvinBot wants to merge 2 commits into
Conversation
Replaces the external system camera intent with an in-app VisionCamera modal for chat attachment photos (re-land of PR 87681). Routes the camera launch through onModalHide so the camera modal only presents after the picker popover has fully dismissed, fixing the iOS modal-presentation race that caused the camera to not open / the app to load infinitely. Co-authored-by: Shridhar Goel <ShridharGoel@users.noreply.github.com>
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/es.ts b/src/languages/es.ts
index b5a66776904..5b9aa296e68 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1175,7 +1175,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: 'Suéltalo',
dropMessage: 'Suelta tu archivo aquí',
flash: 'flash',
- flipCamera: 'Cambiar cámara',
+ flipCamera: 'Cambiar de cámara',
multiScan: 'escaneo múltiple',
shutter: 'obturador',
gallery: 'galería',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 1705d428725..4f7369240b1 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1215,7 +1215,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: 'Lascia perdere',
dropMessage: 'Rilascia qui il tuo file',
flash: 'flash',
- flipCamera: 'Cambia fotocamera',
+ flipCamera: 'Inverti fotocamera',
multiScan: 'scansione multipla',
shutter: 'otturatore',
gallery: 'galleria',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 209479d4d6d..f304a4f123c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1198,7 +1198,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: '手放して',
dropMessage: 'ここにファイルをドロップしてください',
flash: 'フラッシュ',
- flipCamera: 'カメラ切替',
+ flipCamera: 'カメラを反転',
multiScan: 'マルチスキャン',
shutter: 'シャッター',
gallery: 'ギャラリー',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 2bf3f415309..48682eb22e3 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1214,7 +1214,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: 'Laat het los',
dropMessage: 'Zet je bestand hier neer',
flash: 'flits',
- flipCamera: 'Camera wisselen',
+ flipCamera: 'Camera omdraaien',
multiScan: 'meerscannen',
shutter: 'sluiter',
gallery: 'galerij',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index c6429c56266..0861b845200 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1210,7 +1210,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: 'Odpuść to',
dropMessage: 'Upuść tutaj plik',
flash: 'błysk',
- flipCamera: 'Przełącz kamerę',
+ flipCamera: 'Obróć kamerę',
multiScan: 'wielokrotne skanowanie',
shutter: 'migawka',
gallery: 'galeria',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 8aca0907787..0ec7a8fd340 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1214,7 +1214,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: 'Deixe pra lá',
dropMessage: 'Solte seu arquivo aqui',
flash: 'flash',
- flipCamera: 'Alternar câmera',
+ flipCamera: 'Inverter câmera',
multiScan: 'escaneamento múltiplo',
shutter: 'obturador',
gallery: 'galeria',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index d6332d8b119..f39d6bdb7b9 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1166,7 +1166,7 @@ const translations: TranslationDeepObject<typeof en> = {
dropTitle: '随它去',
dropMessage: '将文件拖放到此处',
flash: '闪光',
- flipCamera: '切换相机',
+ flipCamera: '切换摄像头',
multiScan: '多重扫描',
shutter: '快门',
gallery: '图库',
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
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.
|
Move the cameraRef.current access into a module-level helper so React Compiler does not flag ref access during render. OXC previously bailed on the whole file (no memoization on web) while Babel still memoized it, producing a divergence. Co-authored-by: Shridhar Goel <ShridharGoel@users.noreply.github.com>
|
Fixed the failing React Compiler Compliance check and pushed to the branch. Root cause: Fix: Moved the I also removed the now-stale Verification
The other failing check ( |
|
All the code checks are green now — React Compiler Compliance, ESLint, Oxfmt, typecheck, and every unit test pass after my earlier fix. The only remaining failing check is PR Author Checklist, which is a human checklist, not a code failure. There's nothing for me to fix here — |
Explanation of Change
This is a fresh re-land of the in-app VisionCamera flow for chat attachment photos (originally PR #86981, re-implemented in PR #87681, which was reverted). It replaces the external system camera intent with an in-app VisionCamera modal so Expensify stays in the foreground during capture — the original crash (#84018) was the OS reclaiming the backgrounded Expensify process while the system camera was open on Android 16.
Deploy blockers addressed in this re-land
#90047(iOS: in-app camera does not open for avatar) /#90042(iOS: app loads infinitely when taking a photo with camera permission denied). Root cause: an iOS modal-presentation race. The previous version calledclose()on the picker popover and then immediately opened the cameraModal, but iOS silently drops a modal that is presented while another modal is still dismissing — so the camera never appeared (leaving the caller hanging). Fixed by deferring the camera launch toonModalHide(so it only presents after the popover has fully dismissed), reusing the exact pattern the gallery/document flow already relies on for the same iOS quirk.Not verified locally — needs on-device iOS testing before this is marked ready
#90119(iOS: viewfinder blurry/grainy) and#90236(iOS: app theme does not change while in camera mode) are iOS-runtime rendering behaviors that cannot be reproduced or validated without an iOS device. They are called out here so the reviewer verifies them on a device; if either still reproduces, they likely need a VisionCamera format/preview tweak (#90119) and a change away from the RNModalfor theme propagation (#90236) respectively.Excluded as unrelated
#93006(native-share crash) was auto-linked to PR fix: use in-app VisionCamera for chat attachment photos #87681, but its own investigation attributes it to areact-native-blob-util/react-native-svgdependency bump in PR chore: upgradereact-native-blob-utilto 0.24.9 #92509 — it is not caused by this feature, so nothing here addresses it.Local checks run and passing:
typecheck-tsgo,lint-changed, andoxfmt. React-compiler compliance will be validated by CI. All manual/on-device testing is left for the human co-author.Fixed Issues
$ #84018
PROPOSAL: #84018 (comment)
Tests
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 stepssectionAvatar, 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.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
Screenshots/Videosundefined