Fix: floating ball's default position blocks touches even when never shown - #440
Conversation
…ven when hidden CustomWindow.point(inside:with:) decides whether to swallow a touch purely by testing the point against ballView's frame (DSFloatChat.ballRect), without checking whether ballView is actually attached to the window. FloatViewManager.setup() assigns ballView.frame as soon as FloatViewManager.shared is first accessed (~1s after DebugSwift.setup() runs via FeatureHandling's delayed FloatViewManager.setup(...) call), but ballView is only added to the window when show is toggled true (FloatBallView.show's didSet). Until then, ballView has a real frame but isn't part of the view hierarchy at all. Any touch inside that 40x40pt rect on the screen's left edge (x: 0, y: screenHeight * 0.3) is silently swallowed, even though the float ball is never shown - a real, invisible dead zone whenever DebugSwift.setup() has run but the ball has never been toggled visible. Fix: only honor the ball hit-test when ballView is actually installed in this window (ballView.window === self).
|
+1 to merging this. Independent confirmation — this still reproduces on current We hit this in a production app: a checkbox on our login screen was "impossible to tap unless you found a magic spot". It took a Environment: Xcode 26.4.1 (17E202), iPhone 17 Pro simulator, iOS 26.0 (402 × 874 pt). Reproduced in this repo's own Example app, public API onlydebugSwift
.setup(enableBetaFeatures: [.swiftUIRenderTracking, .networkSessionPersistence, .agentDebugLog])
.show()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.debugSwift.hide()
}After the ball visibly disappears:
Dead rect Verified this PR's diffApplied
|
Summary
CustomWindow.point(inside:with:)decides whether to swallow a touch purely by testing it againstballView's frame (DSFloatChat.ballRect, i.e.x: 0, y: screenHeight * 0.3, width: 40, height: 40) - it never checks whetherballViewis actually attached to the window.FloatViewManager'ssetup()setsballView.frameas soon asFloatViewManager.sharedis first accessed (in practice ~1s afterDebugSwift.setup()runs, viaFeatureHandling's delayedFloatViewManager.setup(...)call), butballViewis only ever added to the window when it's actually toggled visible (FloatBallView.show'sdidSetcallsaddSubviewonly whenshow == true).ballViewhas a real frame but is not part of the view hierarchy at all. Any touch landing inside that 40x40pt rect on the screen's left edge is silently swallowed byCustomWindow, even though the float ball has never been shown - a real, invisible dead zone, not just a theoretical edge case.ballViewis actually installed in this window (ballView.window === self).Type of change
Test plan
Manual test steps
DebugSwift.setup()at app launch and never call.show()/.toggle().FloatViewManager.setup(...)to run (lazily initializesFloatViewManager.shared, which setsballView.frame).x: 0...40, y: screenHeight*0.3...screenHeight*0.3+40(left screen edge, ~30% down).ballView.point(inside:)returnstruepurely from frame geometry). After this fix: the tap passes through normally, sinceballView.windowisnilat that point.I reproduced this with instrumented logging in a real app build (confirmed
rawHit=true, inHierarchy=falseat that exact coordinate before the fix, and confirmed touches pass through correctly after applying it), then verified manually in a simulator running the patched build.Checklist