From d35de24756165c32dc6edf48a6831563fd3fcb01 Mon Sep 17 00:00:00 2001 From: daledah Date: Fri, 22 Nov 2024 14:15:15 +0700 Subject: [PATCH 1/3] fix: Text in search field does not move to the end --- .../Search/SearchRouter/SearchRouter.tsx | 27 +++++++++++- .../Search/SearchRouter/SearchRouterInput.tsx | 43 +++++++++++-------- .../Search/SearchRouter/SearchRouterList.tsx | 4 +- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index b05d34b2351b..a49c856d6a9c 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -19,6 +19,7 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CardUtils from '@libs/CardUtils'; +import type {ScrollToBottom} from '@libs/InputUtils/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import {getAllTaxRates} from '@libs/PolicyUtils'; import type {OptionData} from '@libs/ReportUtils'; @@ -324,13 +325,36 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) ], ); + const scrollToRight: ScrollToBottom = (input) => { + if (!('scrollLeft' in input)) { + return; + } + // Scroll to the far right + // eslint-disable-next-line no-param-reassign + input.scrollLeft = input.scrollWidth; + }; + + const shouldScrollRef = useRef(false); + const searchRouterInputRef = useRef(null); + // Trigger scrollToRight when input value changes and shouldScroll is true + useEffect(() => { + if (!searchRouterInputRef.current) { + return; + } + scrollToRight(searchRouterInputRef.current); + shouldScrollRef.current = false; + }, [debouncedInputValue]); + const prevUserQueryRef = useRef(null); useEffect(() => { Report.searchInServer(debouncedInputValue.trim()); }, [debouncedInputValue]); const onSearchChange = useCallback( - (userQuery: string) => { + (userQuery: string, autoScrollToRight = false) => { + if (autoScrollToRight) { + shouldScrollRef.current = true; + } let newUserQuery = userQuery; if (autocompleteSuggestions && userQuery.endsWith(',')) { newUserQuery = `${userQuery.slice(0, userQuery.length - 1).trim()},`; @@ -398,6 +422,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) )} { diff --git a/src/components/Search/SearchRouter/SearchRouterInput.tsx b/src/components/Search/SearchRouter/SearchRouterInput.tsx index 6b99588a21df..b252ca1db069 100644 --- a/src/components/Search/SearchRouter/SearchRouterInput.tsx +++ b/src/components/Search/SearchRouter/SearchRouterInput.tsx @@ -1,10 +1,11 @@ -import type {ReactNode, RefObject} from 'react'; -import React, {useState} from 'react'; +import type {ForwardedRef, ReactNode, RefObject} from 'react'; +import React, {forwardRef, useState} from 'react'; import type {StyleProp, TextInputProps, ViewStyle} from 'react-native'; import {View} from 'react-native'; import FormHelpMessage from '@components/FormHelpMessage'; import type {SelectionListHandle} from '@components/SelectionList/types'; import TextInput from '@components/TextInput'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -50,22 +51,25 @@ type SearchRouterInputProps = { isSearchingForReports?: boolean; } & Pick; -function SearchRouterInput({ - value, - updateSearch, - onSubmit = () => {}, - routerListRef, - isFullWidth, - disabled = false, - shouldShowOfflineMessage = false, - autoFocus = true, - caretHidden = false, - wrapperStyle, - wrapperFocusedStyle, - outerWrapperStyle, - rightComponent, - isSearchingForReports, -}: SearchRouterInputProps) { +function SearchRouterInput( + { + value, + updateSearch, + onSubmit = () => {}, + routerListRef, + isFullWidth, + disabled = false, + shouldShowOfflineMessage = false, + autoFocus = true, + caretHidden = false, + wrapperStyle, + wrapperFocusedStyle, + outerWrapperStyle, + rightComponent, + isSearchingForReports, + }: SearchRouterInputProps, + ref: ForwardedRef, +) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [isFocused, setIsFocused] = useState(false); @@ -79,6 +83,7 @@ function SearchRouterInput({ void; + updateSearchValue: (newValue: string, autoScrollToRight?: boolean) => void; /** Callback to update text input value */ setTextInputValue: (text: string) => void; @@ -246,7 +246,7 @@ function SearchRouterList( } if (item.searchItemType === CONST.SEARCH.SEARCH_ROUTER_ITEM_TYPE.CONTEXTUAL_SUGGESTION) { const searchQuery = getContextualSearchQuery(item); - updateSearchValue(`${searchQuery} `); + updateSearchValue(`${searchQuery} `, true); if (item.roomType === CONST.SEARCH.DATA_TYPES.INVOICE && item.autocompleteID) { const autocompleteKey = `${CONST.SEARCH.SYNTAX_FILTER_KEYS.TO}:${item.searchQuery}`; From f7dbac4f26fbbfb66f9bf034e461b0972ec7bda8 Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 25 Nov 2024 23:35:19 +0700 Subject: [PATCH 2/3] refactor: move scrollToRight to InputUtils --- src/components/Search/SearchRouter/SearchRouter.tsx | 13 ++----------- src/libs/InputUtils/index.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index a49c856d6a9c..6d1964b5ecad 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -19,7 +19,7 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CardUtils from '@libs/CardUtils'; -import type {ScrollToBottom} from '@libs/InputUtils/types'; +import * as InputUtils from '@libs/InputUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import {getAllTaxRates} from '@libs/PolicyUtils'; import type {OptionData} from '@libs/ReportUtils'; @@ -325,15 +325,6 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) ], ); - const scrollToRight: ScrollToBottom = (input) => { - if (!('scrollLeft' in input)) { - return; - } - // Scroll to the far right - // eslint-disable-next-line no-param-reassign - input.scrollLeft = input.scrollWidth; - }; - const shouldScrollRef = useRef(false); const searchRouterInputRef = useRef(null); // Trigger scrollToRight when input value changes and shouldScroll is true @@ -341,7 +332,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) if (!searchRouterInputRef.current) { return; } - scrollToRight(searchRouterInputRef.current); + InputUtils.scrollToRight(searchRouterInputRef.current); shouldScrollRef.current = false; }, [debouncedInputValue]); diff --git a/src/libs/InputUtils/index.ts b/src/libs/InputUtils/index.ts index 19943bf3132a..5e274ebfbbd3 100644 --- a/src/libs/InputUtils/index.ts +++ b/src/libs/InputUtils/index.ts @@ -8,6 +8,15 @@ const scrollToBottom: ScrollToBottom = (input) => { input.scrollTop = input.scrollHeight; }; +const scrollToRight: ScrollToBottom = (input) => { + if (!('scrollLeft' in input)) { + return; + } + // Scroll to the far right + // eslint-disable-next-line no-param-reassign + input.scrollLeft = input.scrollWidth; +}; + const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { if (!('setSelectionRange' in input)) { return; @@ -16,4 +25,4 @@ const moveSelectionToEnd: MoveSelectiontoEnd = (input) => { input.setSelectionRange(length, length); }; -export {scrollToBottom, moveSelectionToEnd}; +export {scrollToBottom, moveSelectionToEnd, scrollToRight}; From eb61515becd648248b254385a0f6fbcbce13c58f Mon Sep 17 00:00:00 2001 From: daledah Date: Wed, 27 Nov 2024 02:16:43 +0700 Subject: [PATCH 3/3] fix: native --- src/libs/InputUtils/index.native.ts | 7 ++++--- src/libs/InputUtils/index.ts | 6 +++--- src/libs/InputUtils/types.ts | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libs/InputUtils/index.native.ts b/src/libs/InputUtils/index.native.ts index 3db4280b7d73..6cf00877ca9a 100644 --- a/src/libs/InputUtils/index.native.ts +++ b/src/libs/InputUtils/index.native.ts @@ -1,6 +1,7 @@ -import type {MoveSelectiontoEnd, ScrollToBottom} from './types'; +import type {MoveSelectiontoEnd, ScrollInput} from './types'; -const scrollToBottom: ScrollToBottom = () => {}; +const scrollToBottom: ScrollInput = () => {}; +const scrollToRight: ScrollInput = () => {}; const moveSelectionToEnd: MoveSelectiontoEnd = () => {}; -export {scrollToBottom, moveSelectionToEnd}; +export {scrollToBottom, moveSelectionToEnd, scrollToRight}; diff --git a/src/libs/InputUtils/index.ts b/src/libs/InputUtils/index.ts index 5e274ebfbbd3..e992be5ca233 100644 --- a/src/libs/InputUtils/index.ts +++ b/src/libs/InputUtils/index.ts @@ -1,6 +1,6 @@ -import type {MoveSelectiontoEnd, ScrollToBottom} from './types'; +import type {MoveSelectiontoEnd, ScrollInput} from './types'; -const scrollToBottom: ScrollToBottom = (input) => { +const scrollToBottom: ScrollInput = (input) => { if (!('scrollTop' in input)) { return; } @@ -8,7 +8,7 @@ const scrollToBottom: ScrollToBottom = (input) => { input.scrollTop = input.scrollHeight; }; -const scrollToRight: ScrollToBottom = (input) => { +const scrollToRight: ScrollInput = (input) => { if (!('scrollLeft' in input)) { return; } diff --git a/src/libs/InputUtils/types.ts b/src/libs/InputUtils/types.ts index 875ac6b602e4..394cdb8722ab 100644 --- a/src/libs/InputUtils/types.ts +++ b/src/libs/InputUtils/types.ts @@ -1,6 +1,6 @@ import type {TextInput} from 'react-native'; -type ScrollToBottom = (input: HTMLInputElement | TextInput) => void; +type ScrollInput = (input: HTMLInputElement | TextInput) => void; type MoveSelectiontoEnd = (input: HTMLInputElement | TextInput) => void; -export type {ScrollToBottom, MoveSelectiontoEnd}; +export type {ScrollInput, MoveSelectiontoEnd};