From 12bfe36bb513ce298591ce4a374a04d3b4da3e27 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Wed, 16 Oct 2024 14:45:15 +0200 Subject: [PATCH 1/9] fix query hash so it returns the same value for the same query when searching from searchRouter --- .../Search/SearchRouter/SearchRouter.tsx | 1 + src/libs/SearchUtils.ts | 42 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 924cf366415a9..f074f526b5c6e 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -149,6 +149,7 @@ function SearchRouter() { } closeSearchRouter(); const standardizedQuery = SearchUtils.standardizeQueryJSON(query, cardList, taxRates); + console.log('%%%%%\n', 'standardizedQuery', standardizedQuery); const queryString = SearchUtils.buildSearchQueryString(standardizedQuery); Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: queryString})); clearUserQuery(); diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index ef9f237bd551f..7742f71386d34 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -1,7 +1,7 @@ import cloneDeep from 'lodash/cloneDeep'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import type {ASTNode, QueryFilter, QueryFilters, SearchColumnType, SearchQueryJSON, SearchQueryString, SearchStatus, SortOrder} from '@components/Search/types'; +import type {AdvancedFiltersKeys, ASTNode, QueryFilter, QueryFilters, SearchColumnType, SearchQueryJSON, SearchQueryString, SearchStatus, SortOrder} from '@components/Search/types'; import ChatListItem from '@components/SelectionList/ChatListItem'; import ReportListItem from '@components/SelectionList/Search/ReportListItem'; import TransactionListItem from '@components/SelectionList/Search/TransactionListItem'; @@ -406,8 +406,35 @@ function isSearchResultsEmpty(searchResults: SearchResults) { return !Object.keys(searchResults?.data).some((key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)); } -function getQueryHashFromString(query: SearchQueryString): number { - return UserUtils.hashText(query, 2 ** 32); +function getQueryHash(query: SearchQueryJSON): number { + let hashedString = ''; + if (query.policyID) { + hashedString += `policyID ${query.policyID}`; + } + hashedString += `type ${query.type} `; + hashedString += `status ${query.status} `; + hashedString += `sortBy ${query.sortBy} `; + hashedString += `sortOrder ${query.sortOrder} `; + + Object.keys(query.flatFilters) + .sort() + .forEach((key) => { + const objectToIterate = query.flatFilters?.[key as AdvancedFiltersKeys]; + hashedString += key; + objectToIterate + ?.sort((queryFilter1, queryFilter2) => { + if (queryFilter1.value > queryFilter2.value) { + return 1; + } + return -1; + }) + ?.forEach((queryFilter) => { + hashedString += ` ${queryFilter.operator} ${queryFilter.value}`; + }); + }); + + console.log('%%%%%\n', 'hashedString', hashedString); + return UserUtils.hashText(hashedString, 2 ** 32); } function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths { @@ -541,12 +568,13 @@ function getFilters(queryJSON: SearchQueryJSON) { function buildSearchQueryJSON(query: SearchQueryString) { try { const result = searchParser.parse(query) as SearchQueryJSON; + // console.log('%%%%%\n', 'result', result); const flatFilters = getFilters(result); // Add the full input and hash to the results result.inputQuery = query; - result.hash = getQueryHashFromString(query); result.flatFilters = flatFilters; + result.hash = getQueryHash(result); return result; } catch (e) { console.error(`Error when parsing SearchQuery: "${query}"`, e); @@ -592,6 +620,10 @@ function buildQueryStringFromFilterFormValues(filterValues: Partial Date: Thu, 17 Oct 2024 13:41:37 +0200 Subject: [PATCH 2/9] add tooltip --- .../Search/SearchRouter/SearchButton.tsx | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchButton.tsx b/src/components/Search/SearchRouter/SearchButton.tsx index 7ed22ec8162f2..b68945e76520f 100644 --- a/src/components/Search/SearchRouter/SearchButton.tsx +++ b/src/components/Search/SearchRouter/SearchButton.tsx @@ -3,6 +3,7 @@ import type {StyleProp, ViewStyle} from 'react-native'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import {PressableWithoutFeedback} from '@components/Pressable'; +import Tooltip from '@components/Tooltip'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -23,21 +24,23 @@ function SearchButton({style}: SearchButtonProps) { const {openSearchRouter} = useSearchRouterContext(); return ( - { - Timing.start(CONST.TIMING.SEARCH_ROUTER_RENDER); - Performance.markStart(CONST.TIMING.SEARCH_ROUTER_RENDER); + + { + Timing.start(CONST.TIMING.SEARCH_ROUTER_RENDER); + Performance.markStart(CONST.TIMING.SEARCH_ROUTER_RENDER); - openSearchRouter(); - })} - > - - + openSearchRouter(); + })} + > + + + ); } From 56cdff84845050392d3d48448e6089d68d7eb148 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Thu, 17 Oct 2024 17:22:47 +0200 Subject: [PATCH 3/9] SearchButton paddings --- src/components/HeaderWithBackButton/index.tsx | 4 ++-- src/components/Search/SearchPageHeader.tsx | 2 +- src/libs/SearchUtils.ts | 19 +++++++++---------- src/pages/home/HeaderView.tsx | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index e1843ee506d56..891a68cb38c4e 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -191,7 +191,7 @@ function HeaderWithBackButton({ /> )} {middleContent} - + {children} {shouldShowDownloadButton && ( @@ -263,7 +263,7 @@ function HeaderWithBackButton({ )} - {shouldDisplaySearchRouter && } + {shouldDisplaySearchRouter && } diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 4c383021645f0..e544c13236a10 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -67,7 +67,7 @@ function HeaderWrapper({icon, children, text, value, isCannedQuery, onSubmit, se /> )}
{text}} /> - {children} + {children} ) : ( diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 7742f71386d34..ae4d34dc1c443 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -407,20 +407,20 @@ function isSearchResultsEmpty(searchResults: SearchResults) { } function getQueryHash(query: SearchQueryJSON): number { - let hashedString = ''; + let stringToHash = ''; if (query.policyID) { - hashedString += `policyID ${query.policyID}`; + stringToHash += `policyID ${query.policyID} `; } - hashedString += `type ${query.type} `; - hashedString += `status ${query.status} `; - hashedString += `sortBy ${query.sortBy} `; - hashedString += `sortOrder ${query.sortOrder} `; + stringToHash += `type ${query.type} `; + stringToHash += `status ${query.status} `; + stringToHash += `sortBy ${query.sortBy} `; + stringToHash += `sortOrder ${query.sortOrder} `; Object.keys(query.flatFilters) .sort() .forEach((key) => { const objectToIterate = query.flatFilters?.[key as AdvancedFiltersKeys]; - hashedString += key; + stringToHash += key; objectToIterate ?.sort((queryFilter1, queryFilter2) => { if (queryFilter1.value > queryFilter2.value) { @@ -429,12 +429,11 @@ function getQueryHash(query: SearchQueryJSON): number { return -1; }) ?.forEach((queryFilter) => { - hashedString += ` ${queryFilter.operator} ${queryFilter.value}`; + stringToHash += ` ${queryFilter.operator} ${queryFilter.value}`; }); }); - console.log('%%%%%\n', 'hashedString', hashedString); - return UserUtils.hashText(hashedString, 2 ** 32); + return UserUtils.hashText(stringToHash, 2 ** 32); } function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths { diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 31aaf7cb1f1c4..a4b5ce901f859 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -280,7 +280,7 @@ function HeaderView({report, parentReportAction, reportID, onNavigationMenuButto {isTaskReport && !shouldUseNarrowLayout && ReportUtils.isOpenTaskReport(report, parentReportAction) && } {canJoin && !shouldUseNarrowLayout && joinButton} - + Date: Thu, 17 Oct 2024 18:44:56 +0200 Subject: [PATCH 4/9] show contacts in recent chats list only when user types something in input --- src/components/Search/SearchRouter/SearchRouter.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 2ace0d632d718..632b59bfdb898 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -84,10 +84,13 @@ function SearchRouter({onRouterClose}: SearchRouterProps) { }, [debouncedInputValue, searchOptions]); const recentReports: OptionData[] = useMemo(() => { - const currentSearchOptions = debouncedInputValue === '' ? searchOptions : filteredOptions; - const reports: OptionData[] = [...currentSearchOptions.recentReports, ...currentSearchOptions.personalDetails]; - if (currentSearchOptions.userToInvite) { - reports.push(currentSearchOptions.userToInvite); + if (debouncedInputValue === '') { + return searchOptions.recentReports.slice(0, 10); + } + + const reports: OptionData[] = [...filteredOptions.recentReports, ...filteredOptions.personalDetails]; + if (filteredOptions.userToInvite) { + reports.push(filteredOptions.userToInvite); } return reports.slice(0, 10); }, [debouncedInputValue, filteredOptions, searchOptions]); From 3fd262dac2805bfd75f592c26cee5f2e26704258 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Thu, 17 Oct 2024 22:57:41 +0200 Subject: [PATCH 5/9] clean up code --- .../Search/SearchRouter/SearchRouter.tsx | 1 - src/libs/SearchUtils.ts | 24 +++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 632b59bfdb898..36cadd4865283 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -148,7 +148,6 @@ function SearchRouter({onRouterClose}: SearchRouterProps) { } onRouterClose(); const standardizedQuery = SearchUtils.standardizeQueryJSON(query, cardList, taxRates); - console.log('%%%%%\n', 'standardizedQuery', standardizedQuery); const queryString = SearchUtils.buildSearchQueryString(standardizedQuery); Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: queryString})); clearUserQuery(); diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index ae4d34dc1c443..9f1ea28964073 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -407,21 +407,21 @@ function isSearchResultsEmpty(searchResults: SearchResults) { } function getQueryHash(query: SearchQueryJSON): number { - let stringToHash = ''; + let orderedQuery = ''; if (query.policyID) { - stringToHash += `policyID ${query.policyID} `; + orderedQuery += `policyID ${query.policyID} `; } - stringToHash += `type ${query.type} `; - stringToHash += `status ${query.status} `; - stringToHash += `sortBy ${query.sortBy} `; - stringToHash += `sortOrder ${query.sortOrder} `; + orderedQuery += `type ${query.type} `; + orderedQuery += ` status ${query.status}`; + orderedQuery += ` sortBy ${query.sortBy} `; + orderedQuery += ` sortOrder ${query.sortOrder} `; Object.keys(query.flatFilters) .sort() .forEach((key) => { - const objectToIterate = query.flatFilters?.[key as AdvancedFiltersKeys]; - stringToHash += key; - objectToIterate + const filterValues = query.flatFilters?.[key as AdvancedFiltersKeys]; + orderedQuery += ` ${key}`; + filterValues ?.sort((queryFilter1, queryFilter2) => { if (queryFilter1.value > queryFilter2.value) { return 1; @@ -429,11 +429,11 @@ function getQueryHash(query: SearchQueryJSON): number { return -1; }) ?.forEach((queryFilter) => { - stringToHash += ` ${queryFilter.operator} ${queryFilter.value}`; + orderedQuery += ` ${queryFilter.operator} ${queryFilter.value}`; }); }); - return UserUtils.hashText(stringToHash, 2 ** 32); + return UserUtils.hashText(orderedQuery, 2 ** 32); } function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths { @@ -619,7 +619,6 @@ function buildQueryStringFromFilterFormValues(filterValues: Partial Date: Fri, 18 Oct 2024 11:19:36 +0200 Subject: [PATCH 6/9] fix PR comments --- src/libs/SearchUtils.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 9f1ea28964073..5d6ecd4d57f9f 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -409,12 +409,12 @@ function isSearchResultsEmpty(searchResults: SearchResults) { function getQueryHash(query: SearchQueryJSON): number { let orderedQuery = ''; if (query.policyID) { - orderedQuery += `policyID ${query.policyID} `; + orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID} ${query.policyID} `; } - orderedQuery += `type ${query.type} `; - orderedQuery += ` status ${query.status}`; - orderedQuery += ` sortBy ${query.sortBy} `; - orderedQuery += ` sortOrder ${query.sortOrder} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE} ${query.type} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS} ${query.status}`; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY} ${query.sortBy} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER} ${query.sortOrder} `; Object.keys(query.flatFilters) .sort() @@ -567,7 +567,6 @@ function getFilters(queryJSON: SearchQueryJSON) { function buildSearchQueryJSON(query: SearchQueryString) { try { const result = searchParser.parse(query) as SearchQueryJSON; - // console.log('%%%%%\n', 'result', result); const flatFilters = getFilters(result); // Add the full input and hash to the results From 0687b54a52ed9bb5992aef498cff2c24c3956ef1 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Fri, 18 Oct 2024 11:29:45 +0200 Subject: [PATCH 7/9] fix orderedQuery structure --- src/libs/SearchUtils.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 5d6ecd4d57f9f..bd7d4cfeb6962 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -411,16 +411,16 @@ function getQueryHash(query: SearchQueryJSON): number { if (query.policyID) { orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID} ${query.policyID} `; } - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE} ${query.type} `; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS} ${query.status}`; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY} ${query.sortBy} `; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER} ${query.sortOrder} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}: ${query.type} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}: ${query.status}`; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}: ${query.sortBy} `; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER}: ${query.sortOrder} `; Object.keys(query.flatFilters) .sort() .forEach((key) => { const filterValues = query.flatFilters?.[key as AdvancedFiltersKeys]; - orderedQuery += ` ${key}`; + orderedQuery += ` ${key}:`; filterValues ?.sort((queryFilter1, queryFilter2) => { if (queryFilter1.value > queryFilter2.value) { From f61b280a1a0b74c982ed3f38519c1944834f1038 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Fri, 18 Oct 2024 14:33:52 +0200 Subject: [PATCH 8/9] fix pr comments --- .../Search/SearchRouter/SearchRouterList.tsx | 6 ++-- src/libs/SearchUtils.ts | 28 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 9830ea4e9506d..096b4fb25b41d 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -32,7 +32,7 @@ type SearchRouterListProps = { currentQuery: SearchQueryJSON | undefined; /** Recent searches */ - recentSearches: ItemWithQuery[] | undefined; + recentSearches: Array | undefined; /** Recent reports */ recentReports: OptionData[]; @@ -129,13 +129,13 @@ function SearchRouterList( }); } - const recentSearchesData = recentSearches?.map(({query}) => { + const recentSearchesData = recentSearches?.map(({query, timestamp}) => { const searchQueryJSON = SearchUtils.buildSearchQueryJSON(query); return { text: searchQueryJSON ? SearchUtils.getSearchHeaderTitle(searchQueryJSON, personalDetails, cardList, reports, taxRates) : query, singleIcon: Expensicons.History, query, - keyForList: query, + keyForList: timestamp, }; }); diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index bd7d4cfeb6962..2977b42144c25 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -409,28 +409,24 @@ function isSearchResultsEmpty(searchResults: SearchResults) { function getQueryHash(query: SearchQueryJSON): number { let orderedQuery = ''; if (query.policyID) { - orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID} ${query.policyID} `; + orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID}:${query.policyID} `; } - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}: ${query.type} `; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}: ${query.status}`; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}: ${query.sortBy} `; - orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER}: ${query.sortOrder} `; + orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${query.type}`; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${query.status}`; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}:${query.sortBy}`; + orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER}:${query.sortOrder}`; Object.keys(query.flatFilters) .sort() .forEach((key) => { const filterValues = query.flatFilters?.[key as AdvancedFiltersKeys]; - orderedQuery += ` ${key}:`; - filterValues - ?.sort((queryFilter1, queryFilter2) => { - if (queryFilter1.value > queryFilter2.value) { - return 1; - } - return -1; - }) - ?.forEach((queryFilter) => { - orderedQuery += ` ${queryFilter.operator} ${queryFilter.value}`; - }); + const sortedFilterValues = filterValues?.sort((queryFilter1, queryFilter2) => { + if (queryFilter1.value > queryFilter2.value) { + return 1; + } + return -1; + }); + orderedQuery += `${buildFilterString(key, sortedFilterValues ?? [])}`; }); return UserUtils.hashText(orderedQuery, 2 ** 32); From 6dc170c4d4d7957f242352ddcd3f3f87f1c1b0f7 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Fri, 18 Oct 2024 19:27:23 +0200 Subject: [PATCH 9/9] fix PR comments --- src/libs/SearchUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 2977b42144c25..58ef947e7b9b2 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -426,7 +426,7 @@ function getQueryHash(query: SearchQueryJSON): number { } return -1; }); - orderedQuery += `${buildFilterString(key, sortedFilterValues ?? [])}`; + orderedQuery += ` ${buildFilterString(key, sortedFilterValues ?? [])}`; }); return UserUtils.hashText(orderedQuery, 2 ** 32);