fix: use native modals on iOS & respect safe area

This commit is contained in:
Adrian Castro
2024-03-24 21:24:33 +01:00
parent 8a9b72ef76
commit 44df83c9fb
4 changed files with 46 additions and 22 deletions

View File

@@ -62,6 +62,7 @@
"react-native-change-icon": "^5.0.0", "react-native-change-icon": "^5.0.0",
"react-native-context-menu-view": "^1.14.1", "react-native-context-menu-view": "^1.14.1",
"react-native-gesture-handler": "~2.14.1", "react-native-gesture-handler": "~2.14.1",
"react-native-ios-modal": "^0.1.8",
"react-native-modal": "^13.0.1", "react-native-modal": "^13.0.1",
"react-native-quick-base64": "^2.0.8", "react-native-quick-base64": "^2.0.8",
"react-native-quick-crypto": "^0.6.1", "react-native-quick-crypto": "^0.6.1",

View File

@@ -1,10 +1,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { useEffect } from "react"; import { useEffect } from "react";
import { GestureHandlerRootView } from "react-native-gesture-handler"; import { GestureHandlerRootView } from "react-native-gesture-handler";
// @ts-expect-error - No exported types
import { ModalView } from "react-native-ios-modal";
import { useFonts } from "expo-font"; import { useFonts } from "expo-font";
import { SplashScreen, Stack } from "expo-router"; import { SplashScreen, Stack } from "expo-router";
import FontAwesome from "@expo/vector-icons/FontAwesome"; import FontAwesome from "@expo/vector-icons/FontAwesome";
import { DarkTheme, ThemeProvider } from "@react-navigation/native"; import { DarkTheme, ThemeProvider } from "@react-navigation/native";
import { setupNativeSheet } from "@tamagui/sheet";
import { ToastProvider, ToastViewport } from "@tamagui/toast"; import { ToastProvider, ToastViewport } from "@tamagui/toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { TamaguiProvider, Theme, useTheme } from "tamagui"; import { TamaguiProvider, Theme, useTheme } from "tamagui";
@@ -20,6 +23,8 @@ export {
ErrorBoundary, ErrorBoundary,
} from "expo-router"; } from "expo-router";
setupNativeSheet("ios", ModalView);
export const unstable_settings = { export const unstable_settings = {
// Ensure that reloading on `/modal` keeps a back button present. // Ensure that reloading on `/modal` keeps a back button present.
initialRouteName: "(tabs)", initialRouteName: "(tabs)",

View File

@@ -1,5 +1,5 @@
import type { SheetProps, ViewProps } from "tamagui"; import type { SheetProps, ViewProps } from "tamagui";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { import {
ScrollView, ScrollView,
Separator, Separator,
@@ -22,6 +22,7 @@ function SettingsSheet(props: SheetProps) {
snapPoints={[90]} snapPoints={[90]}
dismissOnSnapToBottom dismissOnSnapToBottom
modal modal
native
animation="spring" animation="spring"
{...props} {...props}
> >
@@ -52,27 +53,29 @@ function SettingsSheetFrame({
children: React.ReactNode; children: React.ReactNode;
isLoading?: boolean; isLoading?: boolean;
}) { }) {
const insets = useSafeAreaInsets();
return ( return (
<SafeAreaProvider> <View style={{flex: 1}} backgroundColor='black'>
<SafeAreaView style={{ flex: 1 }}> <Sheet.Frame
<Sheet.Frame backgroundColor="$playerSettingsBackground"
backgroundColor="$playerSettingsBackground" padding="$5"
padding="$5" left={insets.left}
gap="$4" right={insets.right}
> gap="$4"
{isLoading && ( >
<Spinner {isLoading && (
size="large" <Spinner
color="$loadingIndicator" size="large"
style={{ color="$loadingIndicator"
position: "absolute", style={{
}} position: "absolute",
/> }}
)} />
{!isLoading && children} )}
</Sheet.Frame> {!isLoading && children}
</SafeAreaView> </Sheet.Frame>
</SafeAreaProvider> </View>
); );
} }
@@ -85,9 +88,11 @@ function SettingsHeader({
title: string; title: string;
rightButton?: React.ReactNode; rightButton?: React.ReactNode;
}) { }) {
const insets = useSafeAreaInsets();
return ( return (
<> <>
<View flexDirection="row" alignItems="center" gap="$4"> <View style={{ paddingRight: insets.right }} flexDirection="row" alignItems="center" gap="$4">
{icon} {icon}
<PlayerText flexGrow={1}>{title}</PlayerText> <PlayerText flexGrow={1}>{title}</PlayerText>
{rightButton} {rightButton}

13
pnpm-lock.yaml generated
View File

@@ -158,6 +158,9 @@ importers:
react-native-gesture-handler: react-native-gesture-handler:
specifier: ~2.14.1 specifier: ~2.14.1
version: 2.14.1(react-native@0.73.6)(react@18.2.0) version: 2.14.1(react-native@0.73.6)(react@18.2.0)
react-native-ios-modal:
specifier: ^0.1.8
version: 0.1.8(react-native@0.73.6)(react@18.2.0)
react-native-modal: react-native-modal:
specifier: ^13.0.1 specifier: ^13.0.1
version: 13.0.1(react-native@0.73.6)(react@18.2.0) version: 13.0.1(react-native@0.73.6)(react@18.2.0)
@@ -11538,6 +11541,16 @@ packages:
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0) react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
dev: false dev: false
/react-native-ios-modal@0.1.8(react-native@0.73.6)(react@18.2.0):
resolution: {integrity: sha512-kA068hIhI9+r21OnRXzkRevGjGYTVAYf5kzsIFI15IrCiAkR40dE2lqJtOpnrB3lZ9KZeS0ph59qNNpDSG7xpA==}
peerDependencies:
react: '*'
react-native: '*'
dependencies:
react: 18.2.0
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
dev: false
/react-native-modal@13.0.1(react-native@0.73.6)(react@18.2.0): /react-native-modal@13.0.1(react-native@0.73.6)(react@18.2.0):
resolution: {integrity: sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==} resolution: {integrity: sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==}
peerDependencies: peerDependencies: