Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/components/Search/SearchAutocompleteList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {getAllTaxRates} from '@libs/PolicyUtils';
import {getReportAction} from '@libs/ReportActionsUtils';
import type {OptionData} from '@libs/ReportUtils';
import {formatReportLastMessageText, getReportOrDraftReport, getReportSubtitlePrefix} from '@libs/ReportUtils';
import {getParsableSearchValue} from '@libs/SearchAutocompleteUtils';
import {buildSearchQueryJSON, buildUserReadableQueryString, getQueryWithoutFilters, shouldHighlight} from '@libs/SearchQueryUtils';
import StringUtils from '@libs/StringUtils';
import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
Expand Down Expand Up @@ -592,12 +591,11 @@ function SearchAutocompleteList({

if (autocompleteSuggestions.length > 0) {
const autocompleteData: AutocompleteListItem[] = autocompleteSuggestions.map(({filterKey, text, autocompleteID, mapKey, workspaceIcon}) => {
const value = mapKey && autocompleteID ? getParsableSearchValue(filterKey, text) : text;
return {
text: getAutocompleteDisplayText(filterKey, text),
mapKey: mapKey ? getSubstitutionMapKey(mapKey, value) : undefined,
mapKey: mapKey ? getSubstitutionMapKey(mapKey, text) : undefined,
singleIcon: expensifyIcons.MagnifyingGlass,
searchQuery: value,
searchQuery: text,
autocompleteID,
keyForList: autocompleteID ?? text, // in case we have a unique identifier then use it because text might not be unique
searchItemType: CONST.SEARCH.SEARCH_ROUTER_ITEM_TYPE.AUTOCOMPLETE_SUGGESTION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {SearchQueryJSON} from '@components/Search/types';
import TextInput from '@components/TextInput';

import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -12,6 +13,7 @@ import {getKeywordQueryWithCurrentSearchContext, getQueryWithUpdatedValues, sani
import variables from '@styles/variables';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import KeyboardUtils from '@src/utils/keyboard';

Expand All @@ -27,6 +29,7 @@ type SearchPageInputProps = {

function SearchPageInput({queryJSON, onFocus}: SearchPageInputProps) {
const {translate} = useLocalize();
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const styles = useThemeStyles();
const theme = useTheme();
const {shouldUseNarrowLayout} = useResponsiveLayout();
Expand All @@ -44,7 +47,7 @@ function SearchPageInput({queryJSON, onFocus}: SearchPageInputProps) {

function submitSearch(query: string) {
const queryWithContext = getKeywordQueryWithCurrentSearchContext(query, queryJSON);
const updatedQuery = getQueryWithUpdatedValues(queryWithContext);
const updatedQuery = getQueryWithUpdatedValues(queryWithContext, false, policies);

if (!updatedQuery) {
return;
Expand Down
6 changes: 3 additions & 3 deletions src/components/Search/SearchRouter/SearchRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
const submitSearch = useCallback(
(queryString: SearchQueryString, shouldSkipAmountConversion = false) => {
const queryWithSubstitutions = getQueryWithSubstitutions(queryString, autocompleteSubstitutions, currentUserAccountID);
const updatedQuery = getQueryWithUpdatedValues(queryWithSubstitutions, shouldSkipAmountConversion);
const updatedQuery = getQueryWithUpdatedValues(queryWithSubstitutions, shouldSkipAmountConversion, policies);
if (!updatedQuery) {
return;
}
Expand All @@ -379,7 +379,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
setTextInputValue('');
setAutocompleteQueryValue('');
},
[autocompleteSubstitutions, currentUserAccountID, onRouterClose, setTextInputValue, setShouldResetSearchQuery, isFromSearchPageSearchButton],
[autocompleteSubstitutions, currentUserAccountID, onRouterClose, setTextInputValue, setShouldResetSearchQuery, isFromSearchPageSearchButton, policies],
);

const onListItemPress = useCallback(
Expand Down Expand Up @@ -419,7 +419,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
} else if (item.searchItemType === CONST.SEARCH.SEARCH_ROUTER_ITEM_TYPE.AUTOCOMPLETE_SUGGESTION && textInputValue) {
const fieldKey = item.mapKey?.includes(':') ? item.mapKey.split(':').at(0) : item.mapKey;
const trimmedUserSearchQuery = getTrimmedUserSearchQueryPreservingComma(textInputValue, fieldKey);
const newSearchQuery = `${trimmedUserSearchQuery}${sanitizeSearchValue(item.searchQuery, true)}\u00A0`;
const newSearchQuery = `${trimmedUserSearchQuery}${sanitizeSearchValue(item.searchQuery)}\u00A0`;
onSearchQueryChange(newSearchQuery, true);
setSelection({start: newSearchQuery.length, end: newSearchQuery.length});

Expand Down
25 changes: 6 additions & 19 deletions src/components/Search/SearchRouter/SearchRouterUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type {SearchQueryItem} from '@components/Search/SearchList/ListItem/SearchQueryListItem';

import {getParsableSearchValue} from '@libs/SearchAutocompleteUtils';
import {getPolicyNameWithFallback, sanitizeSearchValue} from '@libs/SearchQueryUtils';

import type {ReportsSplitNavigatorParamList} from '@navigation/types';
Expand Down Expand Up @@ -59,16 +58,13 @@ function getContextualReportData(state: NavigationState | undefined): Contextual

function getContextualSearchAutocompleteKey(item: SearchQueryItem, policies: OnyxCollection<OnyxTypes.Policy>, reports?: OnyxCollection<OnyxTypes.Report>) {
if (item.roomType === CONST.SEARCH.DATA_TYPES.INVOICE) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.TO}:${getParsableSearchValue(CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, item.searchQuery ?? '')}`;
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.TO}:${item.searchQuery ?? ''}`;
}
if (item.roomType === CONST.SEARCH.DATA_TYPES.CHAT) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.IN}:${getParsableSearchValue(CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, item.searchQuery ?? '')}`;
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.IN}:${item.searchQuery ?? ''}`;
}
if (item.roomType === CONST.SEARCH.DATA_TYPES.EXPENSE) {
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.POLICY_ID}:${getParsableSearchValue(
CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID,
item.policyID ? getPolicyNameWithFallback(item.policyID, policies, reports) : '',
)}`;
return `${CONST.SEARCH.SYNTAX_FILTER_KEYS.POLICY_ID}:${item.policyID ? getPolicyNameWithFallback(item.policyID, policies, reports) : ''}`;
}
}

Expand All @@ -78,26 +74,17 @@ function getContextualSearchQuery(item: SearchQueryItem, policies: OnyxCollectio

switch (item.roomType) {
case CONST.SEARCH.DATA_TYPES.EXPENSE:
additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID}:${sanitizeSearchValue(
getParsableSearchValue(CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID, item.policyID ? getPolicyNameWithFallback(item.policyID, policies, reports) : ''),
true,
)}`;
additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID}:${sanitizeSearchValue(item.policyID ? getPolicyNameWithFallback(item.policyID, policies, reports) : '')}`;
break;
case CONST.SEARCH.DATA_TYPES.INVOICE:
additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID}:${item.policyID}`;
if (item.autocompleteID) {
additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO}:${sanitizeSearchValue(
getParsableSearchValue(CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, item.searchQuery ?? ''),
true,
)}`;
additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO}:${sanitizeSearchValue(item.searchQuery ?? '')}`;
}
break;
case CONST.SEARCH.DATA_TYPES.CHAT:
default:
additionalQuery = ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN}:${sanitizeSearchValue(
getParsableSearchValue(CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, item.searchQuery ?? ''),
true,
)}`;
additionalQuery = ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN}:${sanitizeSearchValue(item.searchQuery ?? '')}`;
break;
}
return baseQuery + additionalQuery;
Expand Down
2 changes: 2 additions & 0 deletions src/components/Search/hooks/useUpdateFilterQuery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {getEmptyObject} from '@src/types/utils/EmptyObject';
function useUpdateFilterQuery(queryJSON: SearchQueryJSON | undefined) {
const {translate} = useLocalize();
const [searchAdvancedFiltersForm = getEmptyObject<Partial<SearchAdvancedFiltersForm>>()] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);

function getUpdatedFilterFormValues(currentValues: Partial<SearchAdvancedFiltersForm>, newValues: Partial<SearchAdvancedFiltersForm>) {
const updatedFilterFormValues: Partial<SearchAdvancedFiltersForm> = {
Expand Down Expand Up @@ -42,6 +43,7 @@ function useUpdateFilterQuery(queryJSON: SearchQueryJSON | undefined) {
values,
{view: searchAdvancedFiltersForm.view, groupBy: searchAdvancedFiltersForm.groupBy},
{sortBy: queryJSON?.sortBy, sortOrder: queryJSON?.sortOrder},
policies,
) ?? '';
if (!queryString) {
return;
Expand Down
17 changes: 1 addition & 16 deletions src/libs/SearchAutocompleteUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {SharedValue} from 'react-native-reanimated/lib/typescript/commonTyp

import {getTagNamesFromTagsLists} from './PolicyUtils';
import {parse} from './SearchParser/autocompleteParser';
import {getUserFriendlyValue, sanitizeSearchValue, stripSearchValueQuotes} from './SearchQueryUtils';
import {getUserFriendlyValue} from './SearchQueryUtils';

/**
* Parses given query using the autocomplete parser.
Expand All @@ -25,20 +25,6 @@ function parseForAutocomplete(text: string) {
}
}

/**
* Returns a value that survives a round trip through the parser under the given filter key. Quotes are only dropped
* when the value cannot be read back as one value, because `from` and the other name filters carry them fine while
* `workspace` and `in` do not. Only safe for a value that is swapped for an ID before the query is sent.
*/
function getParsableSearchValue(filterKey: string, value: string) {
const ranges = parseForAutocomplete(`${filterKey}:${sanitizeSearchValue(value, true)}`)?.ranges ?? [];
if (ranges.length === 1 && ranges.at(0)?.value === value) {
return value;
}

return stripSearchValueQuotes(value);
}

/**
* Returns data for computing the `Tag` filter autocomplete list.
*/
Expand Down Expand Up @@ -351,7 +337,6 @@ function getTrimmedUserSearchQueryPreservingComma(textInputValue: string, fieldK

export {
getAutocompleteCategories,
getParsableSearchValue,
getAutocompleteQueryWithComma,
getAutocompleteRecentCategories,
getAutocompleteRecentTags,
Expand Down
Loading
Loading