| 1 | // Pure helpers for native header scroll-edge effects. Kept free of |
| 2 | // react-native / react-navigation imports so they stay unit-testable in node |
| 3 | // (those packages ship untranspiled Flow syntax). |
| 4 | |
| 5 | export type NativeTopScrollEdgeEffect = "automatic" | "soft"; |
| 6 | export type NativeHeaderScrollEdgeEffects = { |
| 7 | readonly top: NativeTopScrollEdgeEffect; |
| 8 | readonly bottom: "hidden"; |
| 9 | readonly left: "hidden"; |
| 10 | readonly right: "hidden"; |
| 11 | }; |
| 12 | |
| 13 | export function nativeTopScrollEdgeEffect( |
| 14 | os: string, |
| 15 | _version: number | string, |
| 16 | ): NativeTopScrollEdgeEffect { |
| 17 | if (os !== "ios") { |
| 18 | return "automatic"; |
| 19 | } |
| 20 | |
| 21 | // The standalone RNS/Mail spike that matched Messages/GitHub used UIKit's |
| 22 | // automatic scroll-edge behavior. Forcing `soft` on iOS 27 makes production |
| 23 | // look like a local overlay instead of sampling the app content edge-to-edge. |
| 24 | return "automatic"; |
| 25 | } |
| 26 | |
| 27 | export function nativeHeaderScrollEdgeEffects( |
| 28 | os: string, |
| 29 | version: number | string, |
| 30 | ): NativeHeaderScrollEdgeEffects { |
| 31 | return { |
| 32 | top: nativeTopScrollEdgeEffect(os, version), |
| 33 | bottom: "hidden", |
| 34 | left: "hidden", |
| 35 | right: "hidden", |
| 36 | }; |
| 37 | } |