[fix](client): apply the window insets so nothing draws under the system bars
React Native has Flutter's SafeArea under another name: react-native-safe-area- context. The app mounted SafeAreaProvider but never consumed a single inset, so on Android 15+ — where targetSdk 36 forces edge-to-edge and the window extends behind both system bars — the Home header's settings gear sat underneath the notification bar and could not be tapped. A single SafeAreaFrame pads the tree by all four insets once, above the navigator, so every present and future screen inherits the safe area instead of each one re-deriving it.
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { StatusBar } from 'react-native';
|
import { StatusBar, View } from 'react-native';
|
||||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import { HeroUINativeProviderRaw } from 'heroui-native/provider-raw';
|
import { HeroUINativeProviderRaw } from 'heroui-native/provider-raw';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { DarkTheme, NavigationContainer, useNavigation } from '@react-navigation/native';
|
import { DarkTheme, NavigationContainer, useNavigation } from '@react-navigation/native';
|
||||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||||
@@ -149,21 +149,50 @@ function Root() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React Native's equivalent of Flutter's `SafeArea`: pad the whole tree by the
|
||||||
|
* platform's window insets once, so no screen can draw its header under the
|
||||||
|
* status bar or its buttons under the navigation bar.
|
||||||
|
*
|
||||||
|
* This is not optional on Android 15+: with `targetSdk 36` the system enforces
|
||||||
|
* edge-to-edge, so the window extends behind both system bars and the app is
|
||||||
|
* responsible for the padding. Without it the Home header's settings gear sat
|
||||||
|
* underneath the notification bar and could not be tapped.
|
||||||
|
*/
|
||||||
|
function SafeAreaFrame({ children }: { children: React.ReactNode }) {
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
paddingTop: insets.top,
|
||||||
|
paddingBottom: insets.bottom,
|
||||||
|
paddingLeft: insets.left,
|
||||||
|
paddingRight: insets.right,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<GestureHandlerRootView style={{ flex: 1, backgroundColor: bg }}>
|
<GestureHandlerRootView style={{ flex: 1, backgroundColor: bg }}>
|
||||||
<StatusBar barStyle="light-content" backgroundColor={bg} />
|
<StatusBar barStyle="light-content" backgroundColor={bg} />
|
||||||
<HeroUINativeProviderRaw>
|
<HeroUINativeProviderRaw>
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<ThemeProvider>
|
<SafeAreaFrame>
|
||||||
<ConnectionProvider>
|
<ThemeProvider>
|
||||||
<AuthProvider>
|
<ConnectionProvider>
|
||||||
<NavigationContainer ref={navigationRef} theme={NAV_THEME}>
|
<AuthProvider>
|
||||||
<Root />
|
<NavigationContainer ref={navigationRef} theme={NAV_THEME}>
|
||||||
</NavigationContainer>
|
<Root />
|
||||||
</AuthProvider>
|
</NavigationContainer>
|
||||||
</ConnectionProvider>
|
</AuthProvider>
|
||||||
</ThemeProvider>
|
</ConnectionProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
</SafeAreaFrame>
|
||||||
</SafeAreaProvider>
|
</SafeAreaProvider>
|
||||||
</HeroUINativeProviderRaw>
|
</HeroUINativeProviderRaw>
|
||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
|
|||||||
Reference in New Issue
Block a user