Skip to content
9 changes: 8 additions & 1 deletion src/Expensify.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ const propTypes = {
/** Tells us if the sidebar has rendered */
isSidebarLoaded: PropTypes.bool,

/** Tells us if the boot splash is auto hide */
isBootSplashAutoHide: PropTypes.bool,

/** Information about a screen share call requested by a GuidesPlus agent */
screenShareRequest: PropTypes.shape({
/** Access token required to join a screen share room, generated by the backend */
Expand All @@ -89,6 +92,7 @@ const defaultProps = {
},
updateAvailable: false,
isSidebarLoaded: false,
isBootSplashAutoHide: true,
screenShareRequest: null,
isCheckingPublicRoom: true,
focusModeNotification: false,
Expand Down Expand Up @@ -121,7 +125,7 @@ function Expensify(props) {
);

const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && hasAttemptedToOpenPublicRoom;
const shouldHideSplash = shouldInit && !isSplashHidden;
const shouldHideSplash = shouldInit && !isSplashHidden && props.isBootSplashAutoHide;

const initializeClient = () => {
if (!Visibility.isVisible()) {
Expand Down Expand Up @@ -265,6 +269,9 @@ export default compose(
isSidebarLoaded: {
key: ONYXKEYS.IS_SIDEBAR_LOADED,
},
isBootSplashAutoHide: {
key: ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE,
},
screenShareRequest: {
key: ONYXKEYS.SCREEN_SHARE_REQUEST,
},
Expand Down
4 changes: 4 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const ONYXKEYS = {
/** Boolean flag set whenever the sidebar has loaded */
IS_SIDEBAR_LOADED: 'isSidebarLoaded',

/** Boolean flag set whenever the sidebar has loaded */
IS_BOOT_SPLASH_AUTO_HIDE: 'isBootSplashAutoHide',

/** Boolean flag set whenever we are searching for reports in the server */
IS_SEARCHING_FOR_REPORTS: 'isSearchingForReports',

Expand Down Expand Up @@ -373,6 +376,7 @@ type OnyxValues = {
[ONYXKEYS.ACTIVE_CLIENTS]: string[];
[ONYXKEYS.DEVICE_ID]: string;
[ONYXKEYS.IS_SIDEBAR_LOADED]: boolean;
[ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE]: boolean;
[ONYXKEYS.PERSISTED_REQUESTS]: OnyxTypes.Request[];
[ONYXKEYS.CURRENT_DATE]: string;
[ONYXKEYS.CREDENTIALS]: OnyxTypes.Credentials;
Expand Down
25 changes: 25 additions & 0 deletions src/libs/actions/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ Onyx.connect({
initWithStoredValues: false,
});

let isBootSplashAutoHide: boolean | null;
Onyx.connect({
key: ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE,
callback: (val) => (isBootSplashAutoHide = val),
initWithStoredValues: true,
});

let preferredLocale: string | null;
Onyx.connect({
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
Expand Down Expand Up @@ -129,6 +136,22 @@ function setSidebarLoaded() {
Performance.markStart(CONST.TIMING.REPORT_INITIAL_RENDER);
}

function preventBootSplashAutoHide() {
if (!isBootSplashAutoHide) {
return;
}

Onyx.set(ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE, false);
}

function resetBootSplashAutoHide() {
if (isBootSplashAutoHide) {
return;
}

Onyx.set(ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE, true);
}

let appState: AppStateStatus;
AppState.addEventListener('change', (nextAppState) => {
if (nextAppState.match(/inactive|background/) && appState === 'active') {
Expand Down Expand Up @@ -531,6 +554,8 @@ export {
setLocale,
setLocaleAndNavigate,
setSidebarLoaded,
preventBootSplashAutoHide,
resetBootSplashAutoHide,
setUpPoliciesAndNavigate,
openProfile,
redirectThirdPartyDesktopSignIn,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import {Image} from 'expo-image';
import PropTypes from 'prop-types';
import React from 'react';
import AndroidBackgroundImage from '@assets/images/home-background--android.svg';
import useThemeStyles from '@hooks/useThemeStyles';
import defaultPropTypes from './propTypes';

const defaultProps = {
onLoadEnd: () => {},
};

const propTypes = {
/** Called when the image load either succeeds or fails. */
onLoadEnd: PropTypes.func,

...defaultPropTypes,
};

function BackgroundImage(props) {
const styles = useThemeStyles();
return (
<Image
source={AndroidBackgroundImage}
pointerEvents={props.pointerEvents}
style={[styles.signInBackground, {width: props.width}]}
onLoadEnd={props.onLoadEnd}
/>
);
}

BackgroundImage.displayName = 'BackgroundImage';
BackgroundImage.propTypes = defaultPropTypes;
BackgroundImage.propTypes = propTypes;
BackgroundImage.defaultProps = defaultProps;

export default BackgroundImage;
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ import defaultPropTypes from './propTypes';

const defaultProps = {
isSmallScreen: false,
onLoadEnd: () => {},
};

const propTypes = {
/** Is the window width narrow, like on a mobile device */
isSmallScreen: PropTypes.bool,

/** Called when the image load either succeeds or fails. */
onLoadEnd: PropTypes.func,

...defaultPropTypes,
};

function BackgroundImage(props) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
Expand All @@ -26,6 +31,7 @@ function BackgroundImage(props) {
<Image
source={src}
style={[styles.signInBackground, StyleUtils.getWidthStyle(props.width)]}
onLoadEnd={props.onLoadEnd}
/>
);
}
Expand Down
13 changes: 12 additions & 1 deletion src/pages/signin/SignInPageLayout/BackgroundImage/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, {useEffect} from 'react';
import DesktopBackgroundImage from '@assets/images/home-background--desktop.svg';
import MobileBackgroundImage from '@assets/images/home-background--mobile.svg';
import useThemeStyles from '@hooks/useThemeStyles';
import defaultPropTypes from './propTypes';

const defaultProps = {
isSmallScreen: false,
onLoadEnd: () => {},
};

const propTypes = {
/** Is the window width narrow, like on a mobile device */
isSmallScreen: PropTypes.bool,

/** Called when the image load either succeeds or fails. */
onLoadEnd: PropTypes.func,

...defaultPropTypes,
};

function BackgroundImage(props) {
const styles = useThemeStyles();

useEffect(() => {
props.onLoadEnd();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return props.isSmallScreen ? (
<MobileBackgroundImage
width={props.width}
Expand Down
18 changes: 17 additions & 1 deletion src/pages/signin/SignInPageLayout/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import PropTypes from 'prop-types';
import React, {forwardRef, useEffect, useImperativeHandle, useMemo, useRef} from 'react';
import React, {forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {ScrollView, View} from 'react-native';
import {withSafeAreaInsets} from 'react-native-safe-area-context';
import SignInGradient from '@assets/images/home-fade-gradient.svg';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import ImageSVG from '@components/ImageSVG';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrevious from '@hooks/usePrevious';
Expand All @@ -13,6 +14,7 @@ import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import SignInPageHero from '@pages/signin/SignInPageHero';
import variables from '@styles/variables';
import * as App from '@userActions/App';
import BackgroundImage from './BackgroundImage';
import Footer from './Footer';
import SignInPageContent from './SignInPageContent';
Expand Down Expand Up @@ -67,6 +69,7 @@ function SignInPageLayout(props) {
let containerStyles = [styles.flex1, styles.signInPageInner];
let contentContainerStyles = [styles.flex1, styles.flexRow];
const {windowHeight} = useWindowDimensions();
const [isLoading, setIsLoading] = useState(true);

// To scroll on both mobile and web, we need to set the container height manually
const containerHeight = windowHeight - props.insets.top - props.insets.bottom;
Expand All @@ -87,6 +90,10 @@ function SignInPageLayout(props) {
scrollPageToTop,
}));

useEffect(() => {
App.preventBootSplashAutoHide();
}, []);

useEffect(() => {
if (prevPreferredLocale !== props.preferredLocale) {
return;
Expand All @@ -99,6 +106,7 @@ function SignInPageLayout(props) {

return (
<View style={containerStyles}>
{isLoading && <FullScreenLoadingIndicator style={[styles.opacity1]} />}
{!props.shouldShowSmallScreen ? (
<View style={contentContainerStyles}>
<ScrollView
Expand Down Expand Up @@ -127,6 +135,10 @@ function SignInPageLayout(props) {
isSmallScreen={false}
pointerEvents="none"
width={variables.signInHeroBackgroundWidth}
onLoadEnd={() => {
setIsLoading(false);
App.resetBootSplashAutoHide();
}}
/>
</View>
<View>
Expand Down Expand Up @@ -166,6 +178,10 @@ function SignInPageLayout(props) {
isSmallScreen
pointerEvents="none"
width={variables.signInHeroBackgroundWidthMobile}
onLoadEnd={() => {
setIsLoading(false);
App.resetBootSplashAutoHide();
}}
/>
<SignInPageContent
welcomeHeader={props.welcomeHeader}
Expand Down
1 change: 1 addition & 0 deletions src/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default function () {
[ONYXKEYS.ACCOUNT]: CONST.DEFAULT_ACCOUNT_DATA,
[ONYXKEYS.NETWORK]: {isOffline: false},
[ONYXKEYS.IS_SIDEBAR_LOADED]: false,
[ONYXKEYS.IS_BOOT_SPLASH_AUTO_HIDE]: true,
[ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true,
[ONYXKEYS.MODAL]: {
isVisible: false,
Expand Down