Skip to content

Show the QR scanner scam warning after the camera permission is granted - #6192

Open
peachbits wants to merge 3 commits into
developfrom
matthew/scan-scam-warning-permission
Open

Show the QR scanner scam warning after the camera permission is granted#6192
peachbits wants to merge 3 commits into
developfrom
matthew/scan-scam-warning-permission

Conversation

@peachbits

@peachbits peachbits commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Description

Asana: QR Scanner - Modal disappears after permission grant

ScanModal chose its entire body from one ternary keyed on state.permissions.camera, and requested that permission from its own mount effect. The scam warning lived only in the not-granted branch, alongside the "enable Camera access in Settings" recovery text.

Redux seeds camera: 'denied', so on a fresh install the modal opened straight into the Settings guidance before the user had ever been asked, the OS prompt landed on top of that, and answering it flipped the ternary. The warning's subtree was then unmounted by React rather than through bridge.resolve, so it disappeared without its exit animation — the reported flash. The only way to read the warning at all was to deny the camera.

showScanModal now runs the three steps in sequence, so none of them can overlap:

  1. Request the OS camera permission, with no Edge modal on screen behind it.
  2. If denied or blocked, show the Settings recovery guidance and stop.
  3. On the first camera use only, wait for an explicit acknowledgement of the scam warning.
  4. Only then mount the scanner.

Waiting for the app to return to the foreground keeps the warning from being presented while it is still coming back from the OS prompt. ScanModal is left as just the camera sheet, with no permission branch to swap.

Notes for review:

  • The scam warning is a non-skippable ConfirmContinueModal, so backdrop tap, swipe-down, hardware back and the close button are all disabled — it takes the checkbox and confirm button to dismiss. That also means it passes no onCancel, so EdgeModal ignores Airship's global clear event; the modal handles clear itself rather than outliving a logout and leaving the caller awaiting a promise that never settles.
  • The acknowledgement is persisted per account as cameraScamWarningShown, written after the modal resolves, so a force-quit mid-warning shows it again.
  • ScanModal deliberately does not re-check the permission on foreground to swap back to the recovery UI. That branch swap is the flash bug in reverse.
  • WcConnectionsScene picks up return-type and catch-variable fixes that its removal from the ESLint warnings list now requires.

Verification: tsc, eslint and the full jest suite pass. Walked through on the iOS simulator — the OS prompt appears over the plain wallet list with nothing behind it; on Allow the warning appears and stays until the checkbox and Confirm & Finish are tapped; a second scan goes straight to the camera; with camera access revoked, both Side Menu → Scan QR and Send → Scan show only the Settings guidance with no scam warning. Not yet exercised on Android — worth a pass there, since its check() never returns blocked and the app-wide foreground sweep rewrites a blocked camera back to denied, which is why the flow now trusts the status request() returns rather than the redux value.

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Note

Low Risk
UX and modal-flow refactor around QR scanning with no changes to payment or auth logic; main risk is regressions in camera permission or first-scan warning on Android.

Overview
Fixes the QR scanner scam warning flashing away when camera permission is granted by moving orchestration out of ScanModal into a new showScanModal thunk.

The flow is now strictly sequential: request camera permission with no Edge modal behind the OS prompt; if denied/blocked, show CameraPermissionDeniedModal (Settings guidance only); after returning to the foreground, on first camera use show ScanScamWarningModal (non-skippable acknowledge); then mount ScanModal as camera-only. Acknowledgement is stored per account as cameraScamWarningShown via writeCameraScamWarningShown.

Side menu scan, send address scan, and WalletConnect connections now call dispatch(showScanModal(...)) instead of presenting ScanModal directly.

Reviewed by Cursor Bugbot for commit 80ed05d. Bugbot is set up for automated code reviews on this repo. Configure here.

Tracks whether the QR scanner scam warning has been acknowledged, so it
can be shown once on the first use of the camera.
Splits the scam warning apart from the 'enable Camera access' recovery
guidance so the two have independent triggers and lifecycles.

The scam warning is a non-skippable ConfirmContinueModal, so it stays up
until the user ticks the checkbox and confirms. That also leaves it with
no onCancel, which means EdgeModal ignores Airship's global clear event,
so it handles 'clear' itself rather than outliving a logout.
ScanModal chose its whole body from one ternary keyed on the redux camera
permission, and requested that permission from its own mount effect. The
scam warning lived only in the not-granted branch, so on a fresh install
the modal opened straight into 'enable Camera access in Settings' before
the user had ever been asked, the OS prompt landed on top of it, and
answering it flipped the ternary. The warning's subtree was unmounted by
React rather than through bridge.resolve, so it vanished without its exit
animation -- the reported flash. The only way to read the warning was to
deny the camera.

showScanModal now runs the three steps in order, so none of them overlap:
request the permission with no Edge modal on screen behind it, show the
Settings recovery guidance if it was denied or blocked, then on the first
camera use only, wait for an explicit acknowledgement of the scam warning
before mounting the scanner. Waiting for the foreground keeps the warning
from being presented while the app is still returning from the OS prompt.

ScanModal is left as just the camera sheet, with no permission branch to
swap. WcConnectionsScene picks up the return-type and catch-variable
fixes its removal from the ESLint warnings list now requires.
@peachbits
peachbits marked this pull request as ready for review September 3, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant