Skip to content

Commit 818bc44

Browse files
committed
fix: Android - Search - Keyboard is not automatically opened despite input being focused.
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
1 parent 44d8ae5 commit 818bc44

4 files changed

Lines changed: 46 additions & 0 deletions

File tree

src/components/Search/SearchAutocompleteInput.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ function SearchAutocompleteInput(
239239
multiline={false}
240240
parser={parser}
241241
selection={selection}
242+
shouldDelayFocus
242243
/>
243244
</View>
244245
{!!value && (

src/components/TextInput/BaseTextInput/implementation/index.native.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {useFocusEffect} from '@react-navigation/native';
12
import {Str} from 'expensify-common';
23
import type {ForwardedRef} from 'react';
34
import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react';
@@ -78,6 +79,7 @@ function BaseTextInput(
7879
placeholderTextColor,
7980
onClearInput,
8081
iconContainerStyle,
82+
shouldDelayFocus = false,
8183
...props
8284
}: BaseTextInputProps,
8385
ref: ForwardedRef<BaseTextInputRef>,
@@ -92,6 +94,7 @@ function BaseTextInput(
9294
const markdownStyle = useMarkdownStyle(false, excludedMarkdownStyles);
9395
const StyleUtils = useStyleUtils();
9496
const {translate} = useLocalize();
97+
const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);
9598

9699
const {hasError = false} = inputProps;
97100
// Disabling this line for safeness as nullish coalescing works only if the value is undefined or null
@@ -281,6 +284,23 @@ function BaseTextInput(
281284
// Height fix is needed only for Text single line inputs
282285
const shouldApplyHeight = !shouldUseFullInputHeight && !isMultiline && !isMarkdownEnabled;
283286

287+
useFocusEffect(
288+
useCallback(() => {
289+
if (!shouldDelayFocus || !inputProps.autoFocus) {
290+
return;
291+
}
292+
293+
focusTimeoutRef.current = setTimeout(() => {
294+
if (!input.current) {
295+
return;
296+
}
297+
input.current.focus();
298+
}, CONST.ANIMATED_TRANSITION);
299+
300+
return () => focusTimeoutRef.current && clearTimeout(focusTimeoutRef.current);
301+
}, [shouldDelayFocus, inputProps.autoFocus]),
302+
);
303+
284304
return (
285305
<>
286306
<View style={[containerStyles]}>
@@ -417,6 +437,7 @@ function BaseTextInput(
417437
readOnly={isReadOnly}
418438
defaultValue={defaultValue}
419439
markdownStyle={markdownStyle}
440+
autoFocus={shouldDelayFocus ? false : inputProps.autoFocus}
420441
/>
421442
{!!suffixCharacter && (
422443
<View style={[styles.textInputSuffixWrapper, suffixContainerStyle]}>

src/components/TextInput/BaseTextInput/implementation/index.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {useFocusEffect} from '@react-navigation/native';
12
import {Str} from 'expensify-common';
23
import type {ForwardedRef, RefObject} from 'react';
34
import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react';
@@ -80,6 +81,7 @@ function BaseTextInput(
8081
placeholderTextColor,
8182
onClearInput,
8283
iconContainerStyle,
84+
shouldDelayFocus = false,
8385
...inputProps
8486
}: BaseTextInputProps,
8587
ref: ForwardedRef<BaseTextInputRef>,
@@ -94,6 +96,7 @@ function BaseTextInput(
9496
const {hasError = false} = inputProps;
9597
const StyleUtils = useStyleUtils();
9698
const {translate} = useLocalize();
99+
const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);
97100

98101
// Disabling this line for safeness as nullish coalescing works only if value is undefined or null
99102
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -286,6 +289,23 @@ function BaseTextInput(
286289
// If we need some other inputMode (eg. 'decimal'), then the autocomplete bar will show, but we can do nothing about it as it's a known Chrome bug.
287290
const inputMode = inputProps.inputMode ?? (isMobileChrome() ? 'search' : undefined);
288291

292+
useFocusEffect(
293+
useCallback(() => {
294+
if (!shouldDelayFocus || !inputProps.autoFocus) {
295+
return;
296+
}
297+
298+
focusTimeoutRef.current = setTimeout(() => {
299+
if (!input.current) {
300+
return;
301+
}
302+
input.current.focus();
303+
}, CONST.ANIMATED_TRANSITION);
304+
305+
return () => focusTimeoutRef.current && clearTimeout(focusTimeoutRef.current);
306+
}, [shouldDelayFocus, inputProps.autoFocus]),
307+
);
308+
289309
return (
290310
<>
291311
<View
@@ -430,6 +450,7 @@ function BaseTextInput(
430450
readOnly={isReadOnly}
431451
defaultValue={defaultValue}
432452
markdownStyle={markdownStyle}
453+
autoFocus={shouldDelayFocus ? false : inputProps.autoFocus}
433454
/>
434455
{!!suffixCharacter && (
435456
<View style={[styles.textInputSuffixWrapper, suffixContainerStyle]}>

src/components/TextInput/BaseTextInput/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ type CustomBaseTextInputProps = {
186186

187187
/** Whether the input should be enforced to take full height of container. Default is `false` */
188188
shouldUseFullInputHeight?: boolean;
189+
190+
/** Whether focus event should be delayed */
191+
shouldDelayFocus?: boolean;
189192
};
190193

191194
type BaseTextInputRef = HTMLFormElement | AnimatedTextInputRef;

0 commit comments

Comments
 (0)