From 14dc4f952d5ef36fa9b6579ec0eda0cc45972e2b Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 15 Nov 2024 17:05:55 +0800 Subject: [PATCH 1/4] delay search input focus --- src/components/Search/SearchPageHeader.tsx | 1 - .../Search/SearchRouter/SearchRouter.tsx | 3 ++ .../Search/SearchRouter/SearchRouterInput.tsx | 43 ++++++++++--------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 1c3370cd72d5..08a9ca5f0596 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -75,7 +75,6 @@ function HeaderWrapper({icon, children, text, value, isCannedQuery, onSubmit, se value={value} onSubmit={onSubmit} updateSearch={setValue} - autoFocus={false} isFullWidth wrapperStyle={[styles.searchRouterInputResults, styles.br2]} wrapperFocusedStyle={styles.searchRouterInputResultsFocused} diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index e65b12deb64b..55c3b59fd998 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -10,6 +10,7 @@ import {useOptionsList} from '@components/OptionListContextProvider'; import type {SearchAutocompleteQueryRange, SearchQueryString} from '@components/Search/types'; import type {SelectionListHandle} from '@components/SelectionList/types'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; +import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useDebouncedState from '@hooks/useDebouncedState'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; @@ -54,6 +55,7 @@ function SearchRouter({onRouterClose}: SearchRouterProps) { const [betas] = useOnyx(ONYXKEYS.BETAS); const [recentSearches] = useOnyx(ONYXKEYS.RECENT_SEARCHES); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false}); + const {inputCallbackRef} = useAutoFocusInput(); const [autocompleteSuggestions, setAutocompleteSuggestions] = useState([]); const [autocompleteSubstitutions, setAutocompleteSubstitutions] = useState({}); @@ -390,6 +392,7 @@ function SearchRouter({onRouterClose}: SearchRouterProps) { /> )} {}, - routerListRef, - isFullWidth, - disabled = false, - shouldShowOfflineMessage = false, - autoFocus = true, - wrapperStyle, - wrapperFocusedStyle, - outerWrapperStyle, - rightComponent, - isSearchingForReports, -}: SearchRouterInputProps) { +function SearchRouterInput( + { + value, + updateSearch, + onSubmit = () => {}, + routerListRef, + isFullWidth, + disabled = false, + shouldShowOfflineMessage = false, + wrapperStyle, + wrapperFocusedStyle, + outerWrapperStyle, + rightComponent, + isSearchingForReports, + }: SearchRouterInputProps, + ref: ForwardedRef, +) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [isFocused, setIsFocused] = useState(false); @@ -81,11 +83,10 @@ function SearchRouterInput({ Date: Fri, 15 Nov 2024 17:06:03 +0800 Subject: [PATCH 2/4] update input ref type --- src/components/TextInput/BaseTextInput/types.ts | 3 ++- src/components/TimePicker/TimePicker.tsx | 4 ++-- src/hooks/useAutoFocusInput.ts | 10 +++++----- src/libs/InputUtils/types.ts | 6 +++--- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts index c9844e33d594..49a970027778 100644 --- a/src/components/TextInput/BaseTextInput/types.ts +++ b/src/components/TextInput/BaseTextInput/types.ts @@ -1,5 +1,6 @@ import type {MarkdownStyle} from '@expensify/react-native-live-markdown'; import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native'; +import type {AnimatedMarkdownTextInputRef} from '@components/RNMarkdownTextInput'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -144,7 +145,7 @@ type CustomBaseTextInputProps = { contentWidth?: number; }; -type BaseTextInputRef = HTMLFormElement | AnimatedTextInputRef; +type BaseTextInputRef = HTMLFormElement | AnimatedTextInputRef | AnimatedMarkdownTextInputRef; type BaseTextInputProps = CustomBaseTextInputProps & TextInputProps; diff --git a/src/components/TimePicker/TimePicker.tsx b/src/components/TimePicker/TimePicker.tsx index 7f2e34b16b1a..8ce1cfe18362 100644 --- a/src/components/TimePicker/TimePicker.tsx +++ b/src/components/TimePicker/TimePicker.tsx @@ -759,7 +759,7 @@ function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}, shou updateRefs('minuteRef', textInputRef); minuteInputRef.current = textInputRef as TextInput | null; if (!showFullFormat) { - inputCallbackRef(textInputRef as TextInput | null); + inputCallbackRef(textInputRef); } }} onSelectionChange={(e) => { @@ -806,7 +806,7 @@ function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}, shou updateRefs('milisecondRef', textInputRef); milisecondInputRef.current = textInputRef as TextInput | null; if (showFullFormat) { - inputCallbackRef(textInputRef as TextInput | null); + inputCallbackRef(textInputRef); } }} onSelectionChange={(e) => { diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts index c8fdafd417b7..9492dfe1f7bc 100644 --- a/src/hooks/useAutoFocusInput.ts +++ b/src/hooks/useAutoFocusInput.ts @@ -1,15 +1,15 @@ import {useFocusEffect} from '@react-navigation/native'; import {useCallback, useEffect, useRef, useState} from 'react'; import type {RefObject} from 'react'; -import type {TextInput} from 'react-native'; import {InteractionManager} from 'react-native'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import {moveSelectionToEnd, scrollToBottom} from '@libs/InputUtils'; import CONST from '@src/CONST'; import {useSplashScreenStateContext} from '@src/SplashScreenStateContext'; type UseAutoFocusInput = { - inputCallbackRef: (ref: TextInput | null) => void; - inputRef: RefObject; + inputCallbackRef: (ref: BaseTextInputRef | null) => void; + inputRef: RefObject; }; export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInput { @@ -18,7 +18,7 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu const {splashScreenState} = useSplashScreenStateContext(); - const inputRef = useRef(null); + const inputRef = useRef(null); const focusTimeoutRef = useRef(null); useEffect(() => { @@ -53,7 +53,7 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu }, []), ); - const inputCallbackRef = (ref: TextInput | null) => { + const inputCallbackRef = (ref: BaseTextInputRef | null) => { inputRef.current = ref; if (isInputInitialized) { return; diff --git a/src/libs/InputUtils/types.ts b/src/libs/InputUtils/types.ts index 875ac6b602e4..c9d1110397b1 100644 --- a/src/libs/InputUtils/types.ts +++ b/src/libs/InputUtils/types.ts @@ -1,6 +1,6 @@ -import type {TextInput} from 'react-native'; +import {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; -type ScrollToBottom = (input: HTMLInputElement | TextInput) => void; -type MoveSelectiontoEnd = (input: HTMLInputElement | TextInput) => void; +type ScrollToBottom = (input: BaseTextInputRef) => void; +type MoveSelectiontoEnd = (input: BaseTextInputRef) => void; export type {ScrollToBottom, MoveSelectiontoEnd}; From 9ec9fabdb17a8ebae8966814494818935bcb0b56 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 15 Nov 2024 17:25:45 +0800 Subject: [PATCH 3/4] lint --- src/components/Search/SearchRouter/SearchRouterInput.tsx | 3 --- src/libs/InputUtils/index.ts | 2 +- src/libs/InputUtils/types.ts | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouterInput.tsx b/src/components/Search/SearchRouter/SearchRouterInput.tsx index b92a19ea5c68..3a29282200ce 100644 --- a/src/components/Search/SearchRouter/SearchRouterInput.tsx +++ b/src/components/Search/SearchRouter/SearchRouterInput.tsx @@ -34,9 +34,6 @@ type SearchRouterInputProps = { /** Whether the offline message should be shown */ shouldShowOfflineMessage?: boolean; - /** Whether the input should be focused */ - autoFocus?: boolean; - /** Any additional styles to apply */ wrapperStyle?: StyleProp; diff --git a/src/libs/InputUtils/index.ts b/src/libs/InputUtils/index.ts index 19943bf3132a..b7ad4bb7439f 100644 --- a/src/libs/InputUtils/index.ts +++ b/src/libs/InputUtils/index.ts @@ -12,7 +12,7 @@ const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { if (!('setSelectionRange' in input)) { return; } - const length = input.value.length; + const length = (input as HTMLInputElement).value.length; input.setSelectionRange(length, length); }; diff --git a/src/libs/InputUtils/types.ts b/src/libs/InputUtils/types.ts index c9d1110397b1..f032537126e5 100644 --- a/src/libs/InputUtils/types.ts +++ b/src/libs/InputUtils/types.ts @@ -1,4 +1,4 @@ -import {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; type ScrollToBottom = (input: BaseTextInputRef) => void; type MoveSelectiontoEnd = (input: BaseTextInputRef) => void; From 498f385e29b622d6dec50fdf82286a48f60b4241 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 15 Nov 2024 17:30:29 +0800 Subject: [PATCH 4/4] lint --- src/libs/InputUtils/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/InputUtils/index.ts b/src/libs/InputUtils/index.ts index b7ad4bb7439f..760bda3ac798 100644 --- a/src/libs/InputUtils/index.ts +++ b/src/libs/InputUtils/index.ts @@ -12,8 +12,9 @@ const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { if (!('setSelectionRange' in input)) { return; } - const length = (input as HTMLInputElement).value.length; - input.setSelectionRange(length, length); + const inputElement = input as HTMLInputElement; + const length = inputElement.value.length; + inputElement.setSelectionRange(length, length); }; export {scrollToBottom, moveSelectionToEnd};