-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sure the first result in most recents is highlighted when user uses CMD+K #52298
Changes from 16 commits
de6e681
ac997b5
1007716
f03e1e0
dd17a40
fe78ba6
b86b260
2312a87
fd76ed7
e502f95
d3778db
913a059
e9bea23
a9ab802
7861d45
e4e2ab1
ef484ce
4457266
ee1acd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -39,6 +39,7 @@ import CONST from '@src/CONST'; | |||||||||||||||
import ONYXKEYS from '@src/ONYXKEYS'; | ||||||||||||||||
import ROUTES from '@src/ROUTES'; | ||||||||||||||||
import type PersonalDetails from '@src/types/onyx/PersonalDetails'; | ||||||||||||||||
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; | ||||||||||||||||
import {getQueryWithSubstitutions} from './getQueryWithSubstitutions'; | ||||||||||||||||
import type {SubstitutionMap} from './getQueryWithSubstitutions'; | ||||||||||||||||
import {getUpdatedSubstitutionsMap} from './getUpdatedSubstitutionsMap'; | ||||||||||||||||
|
@@ -55,11 +56,13 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) | |||||||||||||||
const styles = useThemeStyles(); | ||||||||||||||||
const {translate} = useLocalize(); | ||||||||||||||||
const [betas] = useOnyx(ONYXKEYS.BETAS); | ||||||||||||||||
const [recentSearches] = useOnyx(ONYXKEYS.RECENT_SEARCHES); | ||||||||||||||||
const [recentSearches, recentSearchesMetadata] = useOnyx(ONYXKEYS.RECENT_SEARCHES); | ||||||||||||||||
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false}); | ||||||||||||||||
const [autocompleteSuggestions, setAutocompleteSuggestions] = useState<AutocompleteItemData[] | undefined>([]); | ||||||||||||||||
const [autocompleteSubstitutions, setAutocompleteSubstitutions] = useState<SubstitutionMap>({}); | ||||||||||||||||
|
||||||||||||||||
const {isLargeScreenWidth} = useResponsiveLayout(); | ||||||||||||||||
|
||||||||||||||||
const {shouldUseNarrowLayout} = useResponsiveLayout(); | ||||||||||||||||
const listRef = useRef<SelectionListHandle>(null); | ||||||||||||||||
|
||||||||||||||||
|
@@ -329,6 +332,11 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) | |||||||||||||||
Report.searchInServer(debouncedInputValue.trim()); | ||||||||||||||||
}, [debouncedInputValue]); | ||||||||||||||||
|
||||||||||||||||
const setInitialFocus = useCallback(() => { | ||||||||||||||||
const initialFocusIndex = (sortedRecentSearches?.slice(0, 5).length ?? 0) + (contextualReportData ? 1 : 0); | ||||||||||||||||
listRef.current?.setFocusedIndex(initialFocusIndex); | ||||||||||||||||
}, [sortedRecentSearches, contextualReportData]); | ||||||||||||||||
|
||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
const onSearchChange = useCallback( | ||||||||||||||||
(userQuery: string) => { | ||||||||||||||||
let newUserQuery = userQuery; | ||||||||||||||||
|
@@ -344,14 +352,16 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) | |||||||||||||||
|
||||||||||||||||
if (newUserQuery || !isEmpty(prevUserQueryRef.current)) { | ||||||||||||||||
listRef.current?.updateAndScrollToFocusedIndex(0); | ||||||||||||||||
} else { | ||||||||||||||||
} else if (!isLargeScreenWidth) { | ||||||||||||||||
listRef.current?.updateAndScrollToFocusedIndex(-1); | ||||||||||||||||
} else { | ||||||||||||||||
setInitialFocus(); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Store the previous newUserQuery | ||||||||||||||||
prevUserQueryRef.current = newUserQuery; | ||||||||||||||||
}, | ||||||||||||||||
[autocompleteSubstitutions, autocompleteSuggestions, setTextInputValue, updateAutocomplete], | ||||||||||||||||
[autocompleteSubstitutions, autocompleteSuggestions, setTextInputValue, updateAutocomplete, isLargeScreenWidth, setInitialFocus], | ||||||||||||||||
); | ||||||||||||||||
|
||||||||||||||||
const onSearchSubmit = useCallback( | ||||||||||||||||
|
@@ -385,6 +395,10 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) | |||||||||||||||
|
||||||||||||||||
const modalWidth = shouldUseNarrowLayout ? styles.w100 : {width: variables.searchRouterPopoverWidth}; | ||||||||||||||||
|
||||||||||||||||
const isDataLoaded = useMemo(() => { | ||||||||||||||||
return (!contextualReportID || contextualReportData !== undefined) && !isLoadingOnyxValue(recentSearchesMetadata) && recentReports.length > 0; | ||||||||||||||||
}, [contextualReportID, contextualReportData, recentSearchesMetadata, recentReports]); | ||||||||||||||||
|
||||||||||||||||
return ( | ||||||||||||||||
<View | ||||||||||||||||
style={[styles.flex1, modalWidth, styles.h100, !shouldUseNarrowLayout && styles.mh85vh]} | ||||||||||||||||
|
@@ -396,34 +410,39 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) | |||||||||||||||
onBackButtonPress={() => onRouterClose()} | ||||||||||||||||
/> | ||||||||||||||||
)} | ||||||||||||||||
<SearchRouterInput | ||||||||||||||||
value={textInputValue} | ||||||||||||||||
isFullWidth={shouldUseNarrowLayout} | ||||||||||||||||
updateSearch={onSearchChange} | ||||||||||||||||
onSubmit={() => { | ||||||||||||||||
onSearchSubmit(textInputValue); | ||||||||||||||||
}} | ||||||||||||||||
caretHidden={shouldHideInputCaret} | ||||||||||||||||
routerListRef={listRef} | ||||||||||||||||
shouldShowOfflineMessage | ||||||||||||||||
wrapperStyle={[styles.border, styles.alignItemsCenter]} | ||||||||||||||||
outerWrapperStyle={[shouldUseNarrowLayout ? styles.mv3 : styles.mv2, shouldUseNarrowLayout ? styles.mh5 : styles.mh2]} | ||||||||||||||||
wrapperFocusedStyle={[styles.borderColorFocus]} | ||||||||||||||||
isSearchingForReports={isSearchingForReports} | ||||||||||||||||
/> | ||||||||||||||||
<SearchRouterList | ||||||||||||||||
textInputValue={textInputValue} | ||||||||||||||||
updateSearchValue={onSearchChange} | ||||||||||||||||
setTextInputValue={setTextInputValue} | ||||||||||||||||
reportForContextualSearch={contextualReportData} | ||||||||||||||||
recentSearches={sortedRecentSearches?.slice(0, 5)} | ||||||||||||||||
recentReports={recentReports} | ||||||||||||||||
autocompleteSuggestions={autocompleteSuggestions} | ||||||||||||||||
onSearchSubmit={onSearchSubmit} | ||||||||||||||||
closeRouter={onRouterClose} | ||||||||||||||||
onAutocompleteSuggestionClick={onAutocompleteSuggestionClick} | ||||||||||||||||
ref={listRef} | ||||||||||||||||
/> | ||||||||||||||||
|
||||||||||||||||
{(isDataLoaded || !!debouncedInputValue) && ( | ||||||||||||||||
nyomanjyotisa marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
<> | ||||||||||||||||
<SearchRouterInput | ||||||||||||||||
value={textInputValue} | ||||||||||||||||
isFullWidth={shouldUseNarrowLayout} | ||||||||||||||||
updateSearch={onSearchChange} | ||||||||||||||||
onSubmit={() => { | ||||||||||||||||
onSearchSubmit(textInputValue); | ||||||||||||||||
}} | ||||||||||||||||
caretHidden={shouldHideInputCaret} | ||||||||||||||||
routerListRef={listRef} | ||||||||||||||||
shouldShowOfflineMessage | ||||||||||||||||
wrapperStyle={[styles.border, styles.alignItemsCenter]} | ||||||||||||||||
outerWrapperStyle={[shouldUseNarrowLayout ? styles.mv3 : styles.mv2, shouldUseNarrowLayout ? styles.mh5 : styles.mh2]} | ||||||||||||||||
wrapperFocusedStyle={[styles.borderColorFocus]} | ||||||||||||||||
isSearchingForReports={isSearchingForReports} | ||||||||||||||||
/> | ||||||||||||||||
<SearchRouterList | ||||||||||||||||
textInputValue={textInputValue} | ||||||||||||||||
updateSearchValue={onSearchChange} | ||||||||||||||||
setTextInputValue={setTextInputValue} | ||||||||||||||||
reportForContextualSearch={contextualReportData} | ||||||||||||||||
recentSearches={sortedRecentSearches?.slice(0, 5)} | ||||||||||||||||
recentReports={recentReports} | ||||||||||||||||
autocompleteSuggestions={autocompleteSuggestions} | ||||||||||||||||
onSearchSubmit={onSearchSubmit} | ||||||||||||||||
closeRouter={onRouterClose} | ||||||||||||||||
onAutocompleteSuggestionClick={onAutocompleteSuggestionClick} | ||||||||||||||||
ref={listRef} | ||||||||||||||||
/> | ||||||||||||||||
</> | ||||||||||||||||
)} | ||||||||||||||||
</View> | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||||||||||
import React, {forwardRef, useCallback} from 'react'; | ||||||||||||||
import React, {forwardRef, useCallback, useEffect, useState} from 'react'; | ||||||||||||||
import type {ForwardedRef} from 'react'; | ||||||||||||||
import {useOnyx} from 'react-native-onyx'; | ||||||||||||||
import type {ValueOf} from 'type-fest'; | ||||||||||||||
|
@@ -148,14 +148,16 @@ function SearchRouterList( | |||||||||||||
) { | ||||||||||||||
const styles = useThemeStyles(); | ||||||||||||||
const {translate} = useLocalize(); | ||||||||||||||
const {shouldUseNarrowLayout} = useResponsiveLayout(); | ||||||||||||||
const {shouldUseNarrowLayout, isLargeScreenWidth} = useResponsiveLayout(); | ||||||||||||||
|
||||||||||||||
const personalDetails = usePersonalDetails(); | ||||||||||||||
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); | ||||||||||||||
const taxRates = getAllTaxRates(); | ||||||||||||||
const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||||||||||||||
const sections: Array<SectionListDataType<OptionData | SearchQueryItem>> = []; | ||||||||||||||
|
||||||||||||||
const [isInitialRender, setIsInitialRender] = useState(true); | ||||||||||||||
|
||||||||||||||
if (textInputValue) { | ||||||||||||||
sections.push({ | ||||||||||||||
data: [ | ||||||||||||||
|
@@ -298,6 +300,13 @@ function SearchRouterList( | |||||||||||||
[setTextInputValue, textInputValue, onAutocompleteSuggestionClick], | ||||||||||||||
); | ||||||||||||||
|
||||||||||||||
useEffect(() => { | ||||||||||||||
if (textInputValue) { | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
setIsInitialRender(true); | ||||||||||||||
}, [textInputValue]); | ||||||||||||||
|
||||||||||||||
return ( | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
<SelectionList<OptionData | SearchQueryItem> | ||||||||||||||
sections={sections} | ||||||||||||||
|
@@ -307,12 +316,17 @@ function SearchRouterList( | |||||||||||||
sectionListStyle={[shouldUseNarrowLayout ? styles.ph5 : styles.ph2, styles.pb2]} | ||||||||||||||
listItemWrapperStyle={[styles.pr0, styles.pl0]} | ||||||||||||||
getItemHeight={getItemHeight} | ||||||||||||||
onLayout={setPerformanceTimersEnd} | ||||||||||||||
onLayout={() => { | ||||||||||||||
setPerformanceTimersEnd(); | ||||||||||||||
setIsInitialRender(false); | ||||||||||||||
}} | ||||||||||||||
ref={ref} | ||||||||||||||
showScrollIndicator={!shouldUseNarrowLayout} | ||||||||||||||
sectionTitleStyles={styles.mhn2} | ||||||||||||||
shouldSingleExecuteRowSelect | ||||||||||||||
onArrowFocus={onArrowFocus} | ||||||||||||||
initiallyFocusedOptionKey={isLargeScreenWidth ? styledRecentReports.at(0)?.keyForList : undefined} | ||||||||||||||
shouldScrollToFocusedIndex={!isInitialRender} | ||||||||||||||
/> | ||||||||||||||
); | ||||||||||||||
} | ||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -114,6 +114,7 @@ function BaseSelectionList<TItem extends ListItem>( | |||||
shouldKeepFocusedItemAtTopOfViewableArea = false, | ||||||
shouldDebounceScrolling = false, | ||||||
shouldPreventActiveCellVirtualization = false, | ||||||
shouldScrollToFocusedIndex = true, | ||||||
}: BaseSelectionListProps<TItem>, | ||||||
ref: ForwardedRef<SelectionListHandle>, | ||||||
) { | ||||||
|
@@ -321,7 +322,9 @@ function BaseSelectionList<TItem extends ListItem>( | |||||
if (focusedItem) { | ||||||
onArrowFocus(focusedItem); | ||||||
} | ||||||
(shouldDebounceScrolling ? debouncedScrollToIndex : scrollToIndex)(index, true); | ||||||
if (shouldScrollToFocusedIndex) { | ||||||
(shouldDebounceScrolling ? debouncedScrollToIndex : scrollToIndex)(index, true); | ||||||
} | ||||||
}, | ||||||
isFocused, | ||||||
}); | ||||||
|
@@ -586,10 +589,12 @@ function BaseSelectionList<TItem extends ListItem>( | |||||
if (!isInitialSectionListRender) { | ||||||
return; | ||||||
} | ||||||
scrollToIndex(focusedIndex, false); | ||||||
if (shouldScrollToFocusedIndex) { | ||||||
scrollToIndex(focusedIndex, false); | ||||||
} | ||||||
setIsInitialSectionListRender(false); | ||||||
}, | ||||||
[focusedIndex, isInitialSectionListRender, scrollToIndex, shouldUseDynamicMaxToRenderPerBatch], | ||||||
[focusedIndex, isInitialSectionListRender, scrollToIndex, shouldUseDynamicMaxToRenderPerBatch, shouldScrollToFocusedIndex], | ||||||
); | ||||||
|
||||||
const onSectionListLayout = useCallback( | ||||||
|
@@ -716,12 +721,13 @@ function BaseSelectionList<TItem extends ListItem>( | |||||
isTextInputFocusedRef.current = isTextInputFocused; | ||||||
}, []); | ||||||
|
||||||
useImperativeHandle(ref, () => ({scrollAndHighlightItem, clearInputAfterSelect, updateAndScrollToFocusedIndex, updateExternalTextInputFocus, scrollToIndex}), [ | ||||||
useImperativeHandle(ref, () => ({scrollAndHighlightItem, clearInputAfterSelect, updateAndScrollToFocusedIndex, updateExternalTextInputFocus, scrollToIndex, setFocusedIndex}), [ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
scrollAndHighlightItem, | ||||||
clearInputAfterSelect, | ||||||
updateAndScrollToFocusedIndex, | ||||||
updateExternalTextInputFocus, | ||||||
scrollToIndex, | ||||||
setFocusedIndex, | ||||||
]); | ||||||
|
||||||
/** Selects row when pressing Enter */ | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.