All files / apps/host/src/screens/AnimatedSplashScreen index.tsx

100% Statements 13/13
100% Branches 2/2
100% Functions 4/4
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                                              1x     3x 3x 3x 3x   3x                 3x 2x   2x   2x           3x                                                                     3x                                            
import React from 'react';
import Animated from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { StyleSheet, View } from 'react-native';
 
import LottieView from 'lottie-react-native';
 
import { makeStyles } from '@repo/ui/themes/makeStyles';
import { useTheme } from '@repo/ui/themes/ThemeContext';
 
import { useAuth } from '@/contexts/AuthContext';
 
import { useAnimatedVisibility } from '@/hooks/useAnimatedVisibility';
 
import { SCREEN_HEIGHT } from '@/utils/dimensions';
 
import { ANIMATION_DURATION, CALLBACK_DELAY, CALLBACK_DELAY_LOGIN } from '@/constants/animation';
import { ASSETS } from '@/constants/assets';
 
interface AnimatedSplashScreenProps {
  onAnimationFinish: (isCancelled: boolean) => void;
}
 
export const AnimatedSplashScreen: React.FC<AnimatedSplashScreenProps> = ({
  onAnimationFinish,
}) => {
  const { theme } = useTheme();
  const styles = useStyles();
  const insets = useSafeAreaInsets();
  const { user } = useAuth();
 
  const { animatedStyle, setVisibility } = useAnimatedVisibility({
    duration: ANIMATION_DURATION,
    initialOpacity: 1,
    initialScale: 1,
    targetOpacity: 0,
    targetScale: 0.5,
    mode: 'in',
  });
 
  const handleLottieAnimationFinish = (isCancelled: boolean) => {
    setVisibility(false);
 
    setTimeout(
      () => {
        onAnimationFinish(isCancelled);
      },
      user ? CALLBACK_DELAY_LOGIN : CALLBACK_DELAY,
    );
  };
 
  return (
    <View
      style={[
        styles.container,
        {
          backgroundColor: theme.colors.ui.darkBlue,
          paddingTop: insets.top,
          paddingBottom: insets.bottom,
        },
      ]}
    >
      <Animated.Image
        source={ASSETS.IMAGES.APP_LOGO}
        style={[styles.logo, { top: insets.top + theme.metrics.spacing[10] }, animatedStyle]}
        resizeMode="contain"
      />
      <LottieView
        source={ASSETS.ANIMATIONS.SPLASH}
        autoPlay
        loop={false}
        resizeMode="cover"
        onAnimationFinish={handleLottieAnimationFinish}
        style={[styles.lottie, { height: SCREEN_HEIGHT }]}
      />
      <LottieView
        source={ASSETS.ANIMATIONS.SIGNIN}
        autoPlay
        loop={false}
        resizeMode="cover"
        style={styles.lottieSignIn}
      />
    </View>
  );
};
 
const useStyles = makeStyles(theme => ({
  container: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 3,
  },
  logo: {
    position: 'absolute',
    width: theme.metrics.spacing[25],
    zIndex: 4,
  },
  lottie: {
    position: 'absolute',
    width: theme.metrics.sizing.full,
  },
  lottieSignIn: {
    position: 'absolute',
    width: theme.metrics.sizing.full,
    zIndex: -1,
  },
}));