/* * This is a reimplementation of what exists in our HTML template files * already. Once the React tree mounts, this is what gets rendered first, until * the app is ready to go. */ import {useEffect, useRef, useState} from 'react' import Svg, {Path} from 'react-native-svg' import {atoms as a, flatten} from '#/alf' const size = 125 const ratio = 512 / 512 export function Splash({ isReady, children, }: React.PropsWithChildren<{ isReady: boolean }>) { const [isAnimationComplete, setIsAnimationComplete] = useState(false) const splashRef = useRef(null) // hide the static one that's baked into the HTML - gets replaced by our React version below useEffect(() => { // double rAF ensures that the React version gets painted first requestAnimationFrame(() => { requestAnimationFrame(() => { const splash = document.getElementById('splash') if (splash) { splash.remove() } }) }) }, []) // when ready, we fade/scale out useEffect(() => { if (!isReady) return const reduceMotion = window.matchMedia( '(prefers-reduced-motion: reduce)', ).matches const node = splashRef.current if (!node || reduceMotion) { setIsAnimationComplete(true) return } const animation = node.animate( [ {opacity: 1, transform: 'scale(1)'}, {opacity: 0, transform: 'scale(1.5)'}, ], { duration: 300, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', fill: 'forwards', }, ) animation.onfinish = () => setIsAnimationComplete(true) return () => { animation.cancel() } }, [isReady]) return ( <> {isReady && children} {!isAnimationComplete && (
)} ) }