|
| 1 | +import { Asset } from "expo-asset"; |
| 2 | +import Constants from "expo-constants"; |
| 3 | +import * as SplashScreen from "expo-splash-screen"; |
| 4 | +import React, { useCallback, useEffect, useMemo, useState } from "react"; |
| 5 | +import { |
| 6 | + Animated, |
| 7 | + View, |
| 8 | + Text, |
| 9 | + Image, |
| 10 | + TouchableOpacity, |
| 11 | + StyleSheet, |
| 12 | +} from "react-native"; |
| 13 | + |
1 | 14 | import { |
2 | 15 | NavigationContainer, |
3 | 16 | useNavigation, |
4 | 17 | DrawerActions, |
5 | 18 | } from "@react-navigation/native"; |
6 | 19 | import { createDrawerNavigator } from "@react-navigation/drawer"; |
7 | 20 | import "react-native-gesture-handler"; |
8 | | -import * as React from "react"; |
9 | | -import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native"; |
| 21 | + |
10 | 22 | import { Provider, DefaultTheme, ScreenContainer } from "@draftbit/ui"; |
11 | 23 | import { |
12 | 24 | SafeAreaProvider, |
13 | 25 | initialWindowMetrics, |
14 | 26 | } from "react-native-safe-area-context"; |
15 | | -import AppLoading from "expo-app-loading"; |
| 27 | + |
16 | 28 | import * as Font from "expo-font"; |
17 | 29 |
|
18 | 30 | import AudioPlayerExample from "./AudioPlayerExample"; |
@@ -128,6 +140,108 @@ const Drawer = createDrawerNavigator(); |
128 | 140 |
|
129 | 141 | type ExampleProps = { title: string; children: React.ReactNode }; |
130 | 142 |
|
| 143 | +SplashScreen.preventAutoHideAsync().catch(() => {}); |
| 144 | + |
| 145 | +export default function App() { |
| 146 | + return ( |
| 147 | + <SplashScreenProvider image={{ uri: Constants.manifest.splash.image }}> |
| 148 | + <Provider theme={DefaultTheme}> |
| 149 | + <SafeAreaProvider initialMetrics={initialWindowMetrics}> |
| 150 | + <Examples /> |
| 151 | + </SafeAreaProvider> |
| 152 | + </Provider> |
| 153 | + </SplashScreenProvider> |
| 154 | + ); |
| 155 | +} |
| 156 | + |
| 157 | +function SplashScreenProvider({ children, image }) { |
| 158 | + const [isSplashReady, setSplashReady] = useState(false); |
| 159 | + |
| 160 | + useEffect(() => { |
| 161 | + async function prepare() { |
| 162 | + try { |
| 163 | + // Pre-load fonts, make any api calls you need to do here |
| 164 | + await Font.loadAsync(customFonts); |
| 165 | + await Asset.fromURI(image.uri).downloadAsync(); |
| 166 | + } catch (e) { |
| 167 | + console.warn(e); |
| 168 | + } finally { |
| 169 | + setSplashReady(true); |
| 170 | + } |
| 171 | + } |
| 172 | + |
| 173 | + prepare(); |
| 174 | + }, [image]); |
| 175 | + |
| 176 | + if (!isSplashReady) { |
| 177 | + return null; |
| 178 | + } |
| 179 | + |
| 180 | + return <AnimatedSplashScreen image={image}>{children}</AnimatedSplashScreen>; |
| 181 | +} |
| 182 | + |
| 183 | +function AnimatedSplashScreen({ children, image }) { |
| 184 | + const animation = useMemo(() => new Animated.Value(1), []); |
| 185 | + const [isAppReady, setAppReady] = useState(false); |
| 186 | + const [isSplashAnimationComplete, setAnimationComplete] = useState(false); |
| 187 | + |
| 188 | + useEffect(() => { |
| 189 | + if (isAppReady) { |
| 190 | + Animated.timing(animation, { |
| 191 | + toValue: 0, |
| 192 | + duration: 1000, |
| 193 | + useNativeDriver: true, |
| 194 | + }).start(() => setAnimationComplete(true)); |
| 195 | + } |
| 196 | + }, [isAppReady, animation]); |
| 197 | + |
| 198 | + const onImageLoaded = useCallback(async () => { |
| 199 | + try { |
| 200 | + await SplashScreen.hideAsync(); |
| 201 | + // Load stuff |
| 202 | + await Promise.all([]); |
| 203 | + } catch (e) { |
| 204 | + // handle errors |
| 205 | + } finally { |
| 206 | + setAppReady(true); |
| 207 | + } |
| 208 | + }, []); |
| 209 | + |
| 210 | + return ( |
| 211 | + <View style={{ flex: 1 }}> |
| 212 | + {isAppReady && children} |
| 213 | + {!isSplashAnimationComplete && ( |
| 214 | + <Animated.View |
| 215 | + pointerEvents="none" |
| 216 | + style={[ |
| 217 | + StyleSheet.absoluteFill, |
| 218 | + { |
| 219 | + backgroundColor: Constants.manifest.splash.backgroundColor, |
| 220 | + opacity: animation, |
| 221 | + }, |
| 222 | + ]} |
| 223 | + > |
| 224 | + <Animated.Image |
| 225 | + style={{ |
| 226 | + width: "100%", |
| 227 | + height: "100%", |
| 228 | + resizeMode: Constants.manifest.splash.resizeMode || "contain", |
| 229 | + transform: [ |
| 230 | + { |
| 231 | + scale: animation, |
| 232 | + }, |
| 233 | + ], |
| 234 | + }} |
| 235 | + source={image} |
| 236 | + onLoadEnd={onImageLoaded} |
| 237 | + fadeDuration={0} |
| 238 | + /> |
| 239 | + </Animated.View> |
| 240 | + )} |
| 241 | + </View> |
| 242 | + ); |
| 243 | +} |
| 244 | + |
131 | 245 | function Example({ title, children }: ExampleProps) { |
132 | 246 | const navigation = useNavigation(); |
133 | 247 |
|
@@ -183,22 +297,6 @@ function Examples() { |
183 | 297 | ); |
184 | 298 | } |
185 | 299 |
|
186 | | -export default function App() { |
187 | | - const [loaded] = Font.useFonts(customFonts); |
188 | | - |
189 | | - if (!loaded) { |
190 | | - return <AppLoading />; |
191 | | - } |
192 | | - |
193 | | - return ( |
194 | | - <Provider theme={DefaultTheme}> |
195 | | - <SafeAreaProvider initialMetrics={initialWindowMetrics}> |
196 | | - <Examples /> |
197 | | - </SafeAreaProvider> |
198 | | - </Provider> |
199 | | - ); |
200 | | -} |
201 | | - |
202 | 300 | const exampleStyles = StyleSheet.create({ |
203 | 301 | mainParent: { |
204 | 302 | width: "100%", |
|
0 commit comments