The drawer gesture's 40px-wide left-edge hitSlop spans the full screen height; its y-position check only ran in onEnd, after the pan had already activated and stolen the touch from the native back-swipe recognizer. Fail the gesture immediately when the touch starts below the header so left-edge back-swipes work everywhere else.
Unified · Split
| @@ -276,6 +276,16 @@ export const ThreadDetailScreen = memo(function ThreadDetailScreen(props: Thread · 275 unmodified lines | ||
| 276 | 276 | .hitSlop({ left: 0, width: 40 }) |
| 277 | 277 | .activeOffsetX([10, 999]) |
| 278 | 278 | .failOffsetY([-24, 24]) |
| 279 | + // Fail at touch-down for anything below the header strip. Activating | |
| 280 | + // there (the y check in onEnd fires too late to matter) swallows the | |
| 281 | + // left-edge touch and blocks the native back-swipe along the whole | |
| 282 | + // screen height. | |
| 283 | + .onTouchesDown((event, stateManager) => { | |
| 284 | + const touchY = event.allTouches[0]?.y ?? Number.POSITIVE_INFINITY; | |
| 285 | + if (touchY >= drawerGestureThreshold) { | |
| 286 | + stateManager.fail(); | |
| 287 | + } | |
| 288 | + }) | |
| 279 | 289 | .onEnd((event) => { |
| 280 | 290 | const translationX = Math.max(event.translationX, 0); |
| 281 | 291 | if (event.y < drawerGestureThreshold && translationX > 56) { |