fix: let host-app touches through when the survey has no overlay [ENG-1818] - #57
Open
pandeymangg wants to merge 1 commit into
Conversation
…-1818] A survey configured with `overlay: none` painted nothing over the host app but still took every touch, so the app appeared frozen until the survey closed. The renderer already sets `pointer-events: none` outside the card, but that is a web hit test: `WKWebView` hit-tests its whole rectangle and UIKit never sees it, and the survey was presented as a full-screen view controller on top. `overlay: none` now gets its own `PassthroughWindow`, masked to the card's rect as the renderer reports it over `onCardRectChange`. Declining a touch there lets UIKit carry on to the host app's window underneath, which a presented view controller cannot do — UIKit's transition container answers for the whole screen even when the content declines. `light` and `dark` keep the existing modal presentation: a visible backdrop is meant to block the host app. No native overlay is painted. That stayed the renderer's job in #39 and still is; this changes hit testing only. Three states, not two, because "no rect has ever arrived" and "the card is not on screen" need different answers. An older self-hosted server serves a renderer that never calls `onCardRectChange`, and the SDK has to keep taking every touch exactly as it used to. Treating that as "claim nothing" is what made the Flutter SDK's survey card untappable when its DOM probe stopped matching. The window is shown rather than made key: taking key status would pull the caret out of whatever the host app has focused, which is the complaint this fixes. UIKit promotes it once the user taps into the survey, so text input still works.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Ref ENG-1818
What & why
Was: a survey with
overlay: nonepainted nothing over the host app but still swallowed every touch, so the app looked frozen until the survey closed.overlayis the default, so this hit every workspace that never configured one.Now: only the survey card takes touches; everything else reaches the host app.
The renderer already sets
pointer-events: noneoutside the card, but that is a web hit test.WKWebViewhit-tests its whole rectangle and UIKit never sees it — and the survey sat in a full-screen presented view controller on top.Where to look
WebView/SurveyTouchRegion.swift— the three states, andPassthroughWindow.hitTestManager/PresentSurveyManager.swift— whyoverlay: nonegets a window instead ofpresent()WebView/FormbricksViewModel.swift— theonCardRectChangebridge functionThree design points worth checking
A window, not a presented controller. Returning
nilfrom a window'shitTestmakes UIKit continue to the next window down — the host app's. A presented view controller cannot do that: UIKit's transition container answers the hit test for the whole screen even when the content declines the touch.Three states, not two. "No rect has ever arrived" and "the card is not on screen" need opposite answers. An older self-hosted server serves a renderer that never calls
onCardRectChange, and the SDK must keep taking every touch as it does today. Treating that as "claim nothing" is exactly what made the Flutter SDK's card untappable when its DOM probe stopped matching.Shown, not made key.
makeKeyAndVisible()would pull the caret out of whatever the host app has focused — the complaint this fixes. UIKit promotes the window once the user taps into the survey, so text input still works.No native overlay is painted; that stayed the renderer's job in #39. This changes hit testing only.
Coverage
overlay: none— host app usable outside the card, survey usable insideoverlay: dark— backdrop visible, host app blockednullrect maps to claiming nothingSurveyTouchRegionTeststestTheDefaultBeforeAnyRectArrivesBlocksLikeBeforerect: nullincludedRerun:
xcodebuild test -scheme FormbricksSDK -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest'Full suite: 122 tests, 0 failures.
Open gaps
sm:) only apply at ≥640pt, so the card is positioned differently there and the rect path is the same code but has not been run.Breaking changes
No public API change.
overlay: nonesurveys stop blocking the host app, which is the fix — a host relying on that block would be relying on the bug.Note
AI model used —
claude-opus-5, reasoning effortunknown.