diff --git a/src/Expensify.js b/src/Expensify.js
index b7e3f0f60567..1b692f86a197 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -90,6 +90,8 @@ const defaultProps = {
isCheckingPublicRoom: true,
};
+const SplashScreenHiddenContext = React.createContext({});
+
function Expensify(props) {
const appStateChangeListener = useRef(null);
const [isNavigationReady, setIsNavigationReady] = useState(false);
@@ -105,6 +107,14 @@ function Expensify(props) {
}, [props.isCheckingPublicRoom]);
const isAuthenticated = useMemo(() => Boolean(lodashGet(props.session, 'authToken', null)), [props.session]);
+
+ const contextValue = useMemo(
+ () => ({
+ isSplashHidden,
+ }),
+ [isSplashHidden],
+ );
+
const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && hasAttemptedToOpenPublicRoom;
const shouldHideSplash = shouldInit && !isSplashHidden;
@@ -216,10 +226,12 @@ function Expensify(props) {
{hasAttemptedToOpenPublicRoom && (
-
+
+
+
)}
{shouldHideSplash && }
@@ -251,3 +263,5 @@ export default compose(
},
}),
)(Expensify);
+
+export {SplashScreenHiddenContext};
diff --git a/src/hooks/useAutoFocusInput.js b/src/hooks/useAutoFocusInput.js
index 181df9359fe8..d4d43c8bf144 100644
--- a/src/hooks/useAutoFocusInput.js
+++ b/src/hooks/useAutoFocusInput.js
@@ -1,21 +1,24 @@
import {useFocusEffect} from '@react-navigation/native';
-import {useCallback, useEffect, useRef, useState} from 'react';
+import {useCallback, useContext, useEffect, useRef, useState} from 'react';
import CONST from '@src/CONST';
+import * as Expensify from '@src/Expensify';
export default function useAutoFocusInput() {
const [isInputInitialized, setIsInputInitialized] = useState(false);
const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
+ const {isSplashHidden} = useContext(Expensify.SplashScreenHiddenContext);
+
const inputRef = useRef(null);
const focusTimeoutRef = useRef(null);
useEffect(() => {
- if (!isScreenTransitionEnded || !isInputInitialized || !inputRef.current) {
+ if (!isScreenTransitionEnded || !isInputInitialized || !inputRef.current || !isSplashHidden) {
return;
}
inputRef.current.focus();
setIsScreenTransitionEnded(false);
- }, [isScreenTransitionEnded, isInputInitialized]);
+ }, [isScreenTransitionEnded, isInputInitialized, isSplashHidden]);
useFocusEffect(
useCallback(() => {
diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js
index f8b041951016..22af82041f7b 100755
--- a/src/pages/NewChatPage.js
+++ b/src/pages/NewChatPage.js
@@ -9,7 +9,7 @@ import OptionsSelector from '@components/OptionsSelector';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
-import useDelayedInputFocus from '@hooks/useDelayedInputFocus';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useNetwork from '@hooks/useNetwork';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
@@ -53,7 +53,6 @@ const defaultProps = {
const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE);
function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, isSearchingForReports}) {
- const optionSelectorRef = React.createRef(null);
const [searchTerm, setSearchTerm] = useState('');
const [filteredRecentReports, setFilteredRecentReports] = useState([]);
const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]);
@@ -216,7 +215,7 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i
setSearchTerm(text);
}, []);
- useDelayedInputFocus(optionSelectorRef, 600);
+ const {inputCallbackRef} = useAutoFocusInput();
return (
0 ? safeAreaPaddingBottomStyle : {}]}>
{isSmallScreenWidth && }
diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js
index cb08d2928d88..131755e02dfa 100644
--- a/src/pages/tasks/TaskAssigneeSelectorModal.js
+++ b/src/pages/tasks/TaskAssigneeSelectorModal.js
@@ -1,7 +1,7 @@
/* eslint-disable es/no-optional-chaining */
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
@@ -11,6 +11,7 @@ import OptionsSelector from '@components/OptionsSelector';
import ScreenWrapper from '@components/ScreenWrapper';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
@@ -80,7 +81,7 @@ function TaskAssigneeSelectorModal(props) {
const [filteredCurrentUserOption, setFilteredCurrentUserOption] = useState(null);
const [isLoading, setIsLoading] = React.useState(true);
- const optionRef = useRef();
+ const {inputCallbackRef} = useAutoFocusInput();
const updateOptions = useCallback(() => {
const {recentReports, personalDetails, userToInvite, currentUserOption} = OptionsListUtils.getFilteredOptions(
@@ -208,7 +209,6 @@ function TaskAssigneeSelectorModal(props) {
return (
optionRef.current && optionRef.current.textInput.focus()}
testID={TaskAssigneeSelectorModal.displayName}
>
{({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => (
@@ -229,7 +229,7 @@ function TaskAssigneeSelectorModal(props) {
textInputLabel={props.translate('optionsSelector.nameEmailOrPhoneNumber')}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
autoFocus={false}
- ref={optionRef}
+ ref={inputCallbackRef}
/>
diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js
index cd0d8166770e..e3f992ea9b5a 100644
--- a/src/pages/tasks/TaskShareDestinationSelectorModal.js
+++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js
@@ -1,6 +1,6 @@
/* eslint-disable es/no-optional-chaining */
import PropTypes from 'prop-types';
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
@@ -8,6 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OptionsSelector from '@components/OptionsSelector';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useNetwork from '@hooks/useNetwork';
import * as Report from '@libs/actions/Report';
import compose from '@libs/compose';
@@ -51,8 +52,9 @@ function TaskShareDestinationSelectorModal(props) {
const [searchValue, setSearchValue] = useState('');
const [headerMessage, setHeaderMessage] = useState('');
const [filteredRecentReports, setFilteredRecentReports] = useState([]);
+
+ const {inputCallbackRef} = useAutoFocusInput();
const {isSearchingForReports} = props;
- const optionRef = useRef();
const {isOffline} = useNetwork();
const filteredReports = useMemo(() => {
@@ -127,7 +129,6 @@ function TaskShareDestinationSelectorModal(props) {
return (
optionRef.current && optionRef.current.textInput.focus()}
testID={TaskShareDestinationSelectorModal.displayName}
>
{({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => (
@@ -151,7 +152,7 @@ function TaskShareDestinationSelectorModal(props) {
textInputAlert={isOffline ? `${props.translate('common.youAppearToBeOffline')} ${props.translate('search.resultsAreLimited')}` : ''}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
autoFocus={false}
- ref={optionRef}
+ ref={inputCallbackRef}
isLoadingNewOptions={isSearchingForReports}
/>
diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js
index 271dc45026c7..ad4bd651fb01 100644
--- a/src/pages/workspace/WorkspaceNewRoomPage.js
+++ b/src/pages/workspace/WorkspaceNewRoomPage.js
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
@@ -13,7 +13,7 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import ValuePicker from '@components/ValuePicker';
import withNavigationFocus from '@components/withNavigationFocus';
-import useDelayedInputFocus from '@hooks/useDelayedInputFocus';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useWindowDimensions from '@hooks/useWindowDimensions';
@@ -161,10 +161,7 @@ function WorkspaceNewRoomPage(props) {
[translate],
);
- const roomNameInputRef = useRef(null);
-
- // use a 600ms delay for delayed focus on the room name input field so that it works consistently on native iOS / Android
- useDelayedInputFocus(roomNameInputRef, 600);
+ const {inputCallbackRef} = useAutoFocusInput();
return (
(roomNameInputRef.current = el)}
+ ref={inputCallbackRef}
inputID="roomName"
isFocused={props.isFocused}
shouldDelayFocus