Skip to content

fix(survey): box-none touch pass-through for non-overlay surveys#19

Open
pandeymangg wants to merge 1 commit into
mainfrom
fix/survey-webview-full-screen
Open

fix(survey): box-none touch pass-through for non-overlay surveys#19
pandeymangg wants to merge 1 commit into
mainfrom
fix/survey-webview-full-screen

Conversation

@pandeymangg

@pandeymangg pandeymangg commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What & why

While a survey was active, the host app received no touch input anywhere — the entire screen was blocked until the survey closed, regardless of placement. This breaks the box-none requirement from ENG-1342 (taps outside the active survey area must reach the host) and RN parity (pointerEvents="box-none").

Fixes ENG-1496.

Root cause

Two independent layers each blocked the full screen:

  1. Modal route barrier — the survey was presented via RawDialogRoute, which always installs a full-screen ModalBarrier. A transparent barrierColor only makes it invisible; it still absorbs every pointer.
  2. Full-bleed WebView — the native WebView hit-tests its whole rectangle, so even with a transparent page and a small survey card, it consumed every touch.

RN gets box-none for free from OS WebView hit-test pass-through (the page's pointer-events:none falls through). Flutter's platform-view embedding hit-tests its entire rect and ignores page-level pointer-events, so the host must mask pointers itself — and it needs the card's geometry to know where the card is.

Approach

Presentation now bifurcates on whether the survey uses a backdrop:

  • Backdrop placements (overlay: dark/light) → keep the full-screen modal route. Blocking the host is correct here; the web runtime draws the dim and handles clickOutside via its existing onClose bridge call.
  • Non-overlay placements (corner/inline cards) → a barrier-less root OverlayEntry wrapped in a _PointerMask. The WebView still paints full-bleed (so shadows render), but only pointers inside the reported card rect hit it; everything outside falls through to the host (box-none). Before geometry arrives, nothing is interactive.

To know the card rect, the survey page now reports it over the JS bridge:

  • A new Geometry message carries the [role="dialog"] card's getBoundingClientRect().
  • A requestAnimationFrame loop tracks the rect during open/step animations and posts only on change, then idles after ~1.5s of stability; MutationObserver + resize/orientationchange restart it on later changes.

Changes

  • webview_event.dart — new GeometryEvent(Rect?) + parser for {type:'Geometry', data:{x,y,width,height}|null}.
  • survey_html.dart — geometry reporting JS; scoped selector #fbjs [role="dialog"][aria-modal="true"].
  • survey_webview.dart — overlay vs non-overlay presentation split, _PointerMask render object, geometry plumbing, unified teardown.

Testing

  • flutter analyze clean; full suite (279 tests) green.
  • New unit tests: geometry parsing (rect / null data / missing data / malformed-drop).
  • New behavioral widget tests: outside-card tap → host; inside-card tap → WebView; pre-geometry → all taps pass through; backdrop → host fully blocked.

🤖 Generated with Claude Code

@pandeymangg pandeymangg changed the title fix: fixes host app touches not passing through bug fix(survey): box-none touch pass-through for non-overlay surveys Jun 18, 2026
@sonarqubecloud

Copy link
Copy Markdown

@pandeymangg pandeymangg requested a review from itsjavi June 18, 2026 10: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