diff --git a/src/hooks/useIsSplashHidden.ts b/src/hooks/useIsSplashHidden.ts new file mode 100644 index 000000000000..7563d388416c --- /dev/null +++ b/src/hooks/useIsSplashHidden.ts @@ -0,0 +1,11 @@ +import {useContext} from 'react'; +import {SplashScreenHiddenContext} from '@src/Expensify'; + +type SplashScreenHiddenContextType = {isSplashHidden: boolean}; + +export default function useIsSplashHidden() { + const {isSplashHidden} = useContext(SplashScreenHiddenContext) as SplashScreenHiddenContextType; + return isSplashHidden; +} + +export type {SplashScreenHiddenContextType}; diff --git a/src/libs/Navigation/getTopmostReportId.ts b/src/libs/Navigation/getTopmostReportId.ts index 4438cb273b84..aac8e7654865 100644 --- a/src/libs/Navigation/getTopmostReportId.ts +++ b/src/libs/Navigation/getTopmostReportId.ts @@ -16,7 +16,7 @@ function getTopmostReportId(state: NavigationState | NavigationState route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR).at(-1); + const topmostCentralPane = state.routes?.filter((route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR).at(-1); if (!topmostCentralPane) { return; } diff --git a/src/pages/signin/SignInHeroImage.js b/src/pages/signin/SignInHeroImage.js index c665a09932c2..8a3db0ea13de 100644 --- a/src/pages/signin/SignInHeroImage.js +++ b/src/pages/signin/SignInHeroImage.js @@ -1,8 +1,10 @@ import PropTypes from 'prop-types'; import React from 'react'; +import {View} from 'react-native'; import Lottie from '@components/Lottie'; import LottieAnimations from '@components/LottieAnimations'; import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; +import useIsSplashHidden from '@hooks/useIsSplashHidden'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; @@ -36,6 +38,14 @@ function SignInHeroImage(props) { }; } + const isSplashHidden = useIsSplashHidden(); + // Prevents rendering of the Lottie animation until the splash screen is hidden + // by returning an empty view of the same size as the animation. + // See issue: https://github.com/Expensify/App/issues/34696 + if (!isSplashHidden) { + return ; + } + return ( (props.isSmallScreen ? MobileBackgroundImage : DesktopBackgroundImage), [props.isSmallScreen]); + + const opacity = useSharedValue(0); + const animatedStyle = useAnimatedStyle(() => ({opacity: opacity.value})); + // This sets the opacity animation for the background image once it has loaded. + function setOpacityAnimation() { + opacity.value = withTiming(1, { + duration: CONST.MICROSECONDS_PER_MS, + easing: Easing.ease, + }); + } + + const isSplashHidden = useIsSplashHidden(); + // Prevent rendering the background image until the splash screen is hidden. + // See issue: https://github.com/Expensify/App/issues/34696 + if (!isSplashHidden) { + return; + } + return ( - + + setOpacityAnimation()} + style={[styles.signInBackground, StyleUtils.getWidthStyle(props.width)]} + transition={props.transitionDuration} + /> + ); } diff --git a/tests/perf-test/SignInPage.perf-test.tsx b/tests/perf-test/SignInPage.perf-test.tsx index 88a653b1fbb9..8baa92ceff49 100644 --- a/tests/perf-test/SignInPage.perf-test.tsx +++ b/tests/perf-test/SignInPage.perf-test.tsx @@ -37,6 +37,7 @@ jest.mock('@react-navigation/native', () => { removeListener: () => jest.fn(), isReady: () => jest.fn(), getCurrentRoute: () => jest.fn(), + getState: () => jest.fn(), }), } as typeof NativeNavigation; });