diff --git a/package.json b/package.json index 2f380e807b..1dda1b412f 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@react-native-clipboard/clipboard": "^1.10.0", "@react-native-community/blur": "^4.3.0", "@react-native-community/datetimepicker": "7.2.0", + "@react-native-masked-view/masked-view": "^0.3.1", "@react-native-menu/menu": "^0.8.0", "@react-native-picker/picker": "2.4.10", "@react-navigation/bottom-tabs": "^6.5.7", diff --git a/src/Splash.tsx b/src/Splash.tsx index 9fc6b3fd99..1aaced850c 100644 --- a/src/Splash.tsx +++ b/src/Splash.tsx @@ -1,9 +1,17 @@ -import React from 'react' -import {View, Image, StyleSheet, Animated, Easing} from 'react-native' -import Constants from 'expo-constants' +import React, {useCallback, useEffect} from 'react' +import {View, Image, StyleSheet} from 'react-native' import * as SplashScreen from 'expo-splash-screen' // @ts-ignore -import splashImagePointer from '../assets/splash.png' +import splashImagePointer from '../assets/icon-android-foreground.png' +import LinearGradient from 'react-native-linear-gradient' +import Animated, { + interpolate, + runOnJS, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated' +import MaskedView from '@react-native-masked-view/masked-view' const splashImageUri = Image.resolveAssetSource(splashImagePointer).uri @@ -14,48 +22,107 @@ type Props = { SplashScreen.preventAutoHideAsync().catch(() => {}) export function Splash(props: React.PropsWithChildren) { - const animation = React.useMemo(() => new Animated.Value(1), []) + const progress = useSharedValue(0) const [isAnimationComplete, setIsAnimationComplete] = React.useState(false) - React.useEffect(() => { - if (props.isReady) { - Animated.timing(animation, { - toValue: 1.5, - duration: 500, - useNativeDriver: true, - easing: Easing.cubic, - }).start(() => setIsAnimationComplete(true)) - } - }, [animation, props.isReady, setIsAnimationComplete]) + const onFinish = useCallback(() => { + SplashScreen.hideAsync().catch(() => {}) + setIsAnimationComplete(true) + }, []) const onLoadEnd = React.useCallback(() => { SplashScreen.hideAsync().catch(() => {}) }, []) - return ( - - {props.children} + useEffect(() => { + if (props.isReady) { + progress.value = withTiming(1, {duration: 1000}, () => { + runOnJS(onFinish)() + }) + } + }, [onFinish, progress, props.isReady]) - {!isAnimationComplete && ( - - - + const imageScale = useAnimatedStyle(() => { + return { + transform: [ + { + scale: interpolate( + progress.value, + [0, 0.2, 1], + [1, 0.8, 100], + 'clamp', + ), + }, + ], + } + }) + + const appScale = useAnimatedStyle(() => { + return { + transform: [ + { + scale: interpolate(progress.value, [0, 1], [1.1, 1]), + }, + ], + } + }) + + const opacityScale = useAnimatedStyle(() => { + return { + opacity: interpolate(progress.value, [0, 0.15, 0.3], [0, 0, 1], 'clamp'), + } + }) + + return ( + + {isAnimationComplete ? null : ( + )} + + + + }> + + {props.children} + + ) } + +import Svg, {SvgProps, Path} from 'react-native-svg' +const Logo = (props: SvgProps) => ( + + + +) diff --git a/yarn.lock b/yarn.lock index c08c37a963..a03eaedbff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4434,6 +4434,11 @@ resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.3.0.tgz#9e558170c106bbafaa1ef502bd8e6d4651012bf9" integrity sha512-+zDZ20NUnSWghj7Ku5aFphMzuM9JulqCW+aPXT6IfIXFbb8tzYTTOSeRFOtuekJ99ibW2fUCSsjuKNlwDIbHFg== +"@react-native-masked-view/masked-view@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.3.1.tgz#5bd76f17004a6ccbcec03856893777ee91f23d29" + integrity sha512-uVm8U6nwFIlUd1iDIB5cS+lDadApKR+l8k4k84d9hn+GN4lzAIJhUZ9syYX7c022MxNgAlbxoFLt0pqKoyaAGg== + "@react-native-menu/menu@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@react-native-menu/menu/-/menu-0.8.0.tgz#dbf227c2081e5ffd3d2073ee68ecc84cf8639727"