diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx
index f1e715bface8..eb04ad5540eb 100755
--- a/src/components/HeaderWithBackButton/index.tsx
+++ b/src/components/HeaderWithBackButton/index.tsx
@@ -7,6 +7,7 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PinButton from '@components/PinButton';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
+import SearchButton from '@components/Search/SearchRouter/SearchButton';
import ThreeDotsMenu from '@components/ThreeDotsMenu';
import Tooltip from '@components/Tooltip';
import useKeyboardState from '@hooks/useKeyboardState';
@@ -60,6 +61,7 @@ function HeaderWithBackButton({
shouldOverlayDots = false,
shouldOverlay = false,
shouldNavigateToTopMostReport = false,
+ shouldDisplaySearchRouter = false,
progressBarPercentage,
style,
}: HeaderWithBackButtonProps) {
@@ -261,6 +263,7 @@ function HeaderWithBackButton({
)}
+ {shouldDisplaySearchRouter && }
diff --git a/src/components/HeaderWithBackButton/types.ts b/src/components/HeaderWithBackButton/types.ts
index c55a7bddc80c..22885b6ceac5 100644
--- a/src/components/HeaderWithBackButton/types.ts
+++ b/src/components/HeaderWithBackButton/types.ts
@@ -128,6 +128,9 @@ type HeaderWithBackButtonProps = Partial & {
/** Whether we should overlay the 3 dots menu */
shouldOverlayDots?: boolean;
+ /** Whether we should display the button that opens new SearchRouter */
+ shouldDisplaySearchRouter?: boolean;
+
/** 0 - 100 number indicating current progress of the progress bar */
progressBarPercentage?: number;
diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx
index 4fc92d619e68..f5e2703b1a47 100644
--- a/src/components/MoneyReportHeader.tsx
+++ b/src/components/MoneyReportHeader.tsx
@@ -285,6 +285,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
report={moneyRequestReport}
policy={policy}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
onBackButtonPress={onBackButtonPress}
// Shows border if no buttons or banners are showing below the header
shouldShowBorderBottom={!isMoreContentShown}
diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx
index 0e0633042a7d..cfe0397bbd11 100644
--- a/src/components/MoneyRequestHeader.tsx
+++ b/src/components/MoneyRequestHeader.tsx
@@ -133,6 +133,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow
}}
policy={policy}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
onBackButtonPress={onBackButtonPress}
>
{hasAllPendingRTERViolations && !shouldUseNarrowLayout && (
diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx
index 73829989409c..704f72055410 100644
--- a/src/components/Search/SearchPageHeader.tsx
+++ b/src/components/Search/SearchPageHeader.tsx
@@ -33,6 +33,7 @@ import type {SearchDataTypes, SearchReport} from '@src/types/onyx/SearchResults'
import type DeepValueOf from '@src/types/utils/DeepValueOf';
import type IconAsset from '@src/types/utils/IconAsset';
import {useSearchContext} from './SearchContext';
+import SearchButton from './SearchRouter/SearchButton';
import type {SearchQueryJSON} from './types';
type HeaderWrapperProps = Pick & {
@@ -295,11 +296,13 @@ function SearchPageHeader({queryJSON, hash, onSelectDeleteOption, setOfflineModa
}
const onPress = () => {
- const values = SearchUtils.getFiltersFormValues(queryJSON);
+ const values = SearchUtils.buildFilterFormValuesFromQuery(queryJSON);
SearchActions.updateAdvancedFilters(values);
Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS);
};
+ const displaySearchRouter = SearchUtils.isCannedSearchQuery(queryJSON);
+
return (
- {headerButtonsOptions.length > 0 ? (
- null}
- shouldAlwaysShowDropdownMenu
- pressOnEnter
- buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
- customText={translate('workspace.common.selected', {selectedNumber: selectedTransactionsKeys.length})}
- options={headerButtonsOptions}
- isSplitButton={false}
- shouldUseStyleUtilityForAnchorPosition
- />
- ) : (
-
- )}
+ <>
+ {headerButtonsOptions.length > 0 ? (
+ null}
+ shouldAlwaysShowDropdownMenu
+ pressOnEnter
+ buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
+ customText={translate('workspace.common.selected', {selectedNumber: selectedTransactionsKeys.length})}
+ options={headerButtonsOptions}
+ isSplitButton={false}
+ shouldUseStyleUtilityForAnchorPosition
+ />
+ ) : (
+
+ )}
+ {displaySearchRouter && }
+ >
);
}
diff --git a/src/components/Search/SearchRouter/SearchButton.tsx b/src/components/Search/SearchRouter/SearchButton.tsx
index 4948c90ce3d1..05693ad5ea22 100644
--- a/src/components/Search/SearchRouter/SearchButton.tsx
+++ b/src/components/Search/SearchRouter/SearchButton.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithoutFeedback} from '@components/Pressable';
+import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Permissions from '@libs/Permissions';
@@ -10,6 +11,7 @@ import {useSearchRouterContext} from './SearchRouterContext';
function SearchButton() {
const styles = useThemeStyles();
const theme = useTheme();
+ const {translate} = useLocalize();
const {openSearchRouter} = useSearchRouterContext();
if (!Permissions.canUseNewSearchRouter()) {
@@ -18,8 +20,8 @@ function SearchButton() {
return (
{
openSearchRouter();
}}
diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx
index 63699d34ce04..dfe2cbbe16c6 100644
--- a/src/components/Search/SearchRouter/SearchRouter.tsx
+++ b/src/components/Search/SearchRouter/SearchRouter.tsx
@@ -14,17 +14,18 @@ import ROUTES from '@src/ROUTES';
import {useSearchRouterContext} from './SearchRouterContext';
import SearchRouterInput from './SearchRouterInput';
-const SEARCH_DEBOUNCE_DELAY = 200;
+const SEARCH_DEBOUNCE_DELAY = 150;
function SearchRouter() {
const styles = useThemeStyles();
const {isSmallScreenWidth} = useResponsiveLayout();
const {isSearchRouterDisplayed, closeSearchRouter} = useSearchRouterContext();
- const [currentQuery, setCurrentQuery] = useState(undefined);
+
+ const [userSearchQuery, setUserSearchQuery] = useState(undefined);
const clearUserQuery = () => {
- setCurrentQuery(undefined);
+ setUserSearchQuery(undefined);
};
const onSearchChange = debounce((userQuery: string) => {
@@ -39,19 +40,24 @@ function SearchRouter() {
// eslint-disable-next-line
console.log('parsedQuery', queryJSON);
- setCurrentQuery(queryJSON);
+ setUserSearchQuery(queryJSON);
} else {
// Handle query parsing error
}
}, SEARCH_DEBOUNCE_DELAY);
const onSearchSubmit = useCallback(() => {
+ if (!userSearchQuery) {
+ return;
+ }
+
closeSearchRouter();
- const query = SearchUtils.buildSearchQueryString(currentQuery);
+ const query = SearchUtils.buildSearchQueryString(userSearchQuery);
Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query}));
+
clearUserQuery();
- }, [currentQuery, closeSearchRouter]);
+ }, [closeSearchRouter, userSearchQuery]);
useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ESCAPE, () => {
closeSearchRouter();
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index 4e23c0883f84..d1080da19932 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -389,6 +389,7 @@ function Search({queryJSON}: SearchProps) {
getItemHeight={getItemHeightMemoized}
shouldSingleExecuteRowSelect
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
+ shouldPreventDefault={false}
listHeaderWrapperStyle={[styles.ph8, styles.pv3, styles.pb5]}
containerStyle={[styles.pv0]}
showScrollIndicator={false}
diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx
index 9ee264bc9bf9..197c64b99a26 100644
--- a/src/components/SelectionList/BaseSelectionList.tsx
+++ b/src/components/SelectionList/BaseSelectionList.tsx
@@ -71,6 +71,7 @@ function BaseSelectionList(
disableKeyboardShortcuts = false,
children,
shouldStopPropagation = false,
+ shouldPreventDefault = true,
shouldShowTooltips = true,
shouldUseDynamicMaxToRenderPerBatch = false,
rightHandSideComponent,
@@ -623,6 +624,7 @@ function BaseSelectionList(
captureOnInputs: true,
shouldBubble: !flattenedSections.allOptions[focusedIndex],
shouldStopPropagation,
+ shouldPreventDefault,
isActive: !disableKeyboardShortcuts && !disableEnterShortcut && isFocused,
});
diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts
index c1085c71e0f6..14c83ef25ed4 100644
--- a/src/components/SelectionList/types.ts
+++ b/src/components/SelectionList/types.ts
@@ -436,9 +436,12 @@ type BaseSelectionListProps = Partial & {
/** Whether tooltips should be shown */
shouldShowTooltips?: boolean;
- /** Whether to stop automatic form submission on pressing enter key or not */
+ /** Whether to stop automatic propagation on pressing enter key or not */
shouldStopPropagation?: boolean;
+ /** Whether to call preventDefault() on pressing enter key or not */
+ shouldPreventDefault?: boolean;
+
/** Whether to prevent default focusing of options and focus the textinput when selecting an option */
shouldPreventDefaultFocusOnSelectRow?: boolean;
diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx
index d06be872c70a..5befa446f6f9 100644
--- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx
+++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx
@@ -14,12 +14,13 @@ import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@libs/actions/Session';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import Navigation from '@libs/Navigation/Navigation';
-import type {RootStackParamList, State} from '@libs/Navigation/types';
+import type {AuthScreensParamList, RootStackParamList, State} from '@libs/Navigation/types';
import {isCentralPaneName} from '@libs/NavigationUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as SearchUtils from '@libs/SearchUtils';
import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
import {getChatTabBrickRoad} from '@libs/WorkspacesSettingsUtils';
+import navigationRef from '@navigation/navigationRef';
import BottomTabAvatar from '@pages/home/sidebar/BottomTabAvatar';
import BottomTabBarFloatingActionButton from '@pages/home/sidebar/BottomTabBarFloatingActionButton';
import variables from '@styles/variables';
@@ -113,9 +114,11 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
return;
}
interceptAnonymousUser(() => {
- const currentSearchParams = SearchUtils.getCurrentSearchParams();
- if (currentSearchParams) {
- const {q, ...rest} = currentSearchParams;
+ const rootState = navigationRef.getRootState() as State;
+ const lastSearchRoute = rootState.routes.filter((route) => route.name === SCREENS.SEARCH.CENTRAL_PANE).at(-1);
+
+ if (lastSearchRoute) {
+ const {q, ...rest} = lastSearchRoute.params as AuthScreensParamList[typeof SCREENS.SEARCH.CENTRAL_PANE];
const cleanedQuery = handleQueryWithPolicyID(q, activeWorkspaceID);
Navigation.navigate(
diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.tsx
index 985c16d50c22..4684eb9637be 100644
--- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.tsx
+++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.tsx
@@ -23,9 +23,9 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
-type TopBarProps = {breadcrumbLabel: string; activeWorkspaceID?: string; shouldDisplaySearch?: boolean; isCustomSearchQuery?: boolean};
+type TopBarProps = {breadcrumbLabel: string; activeWorkspaceID?: string; shouldDisplaySearch?: boolean; isCustomSearchQuery?: boolean; shouldDisplaySearchRouter?: boolean};
-function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true, isCustomSearchQuery = false}: TopBarProps) {
+function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true, isCustomSearchQuery = false, shouldDisplaySearchRouter = false}: TopBarProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();
@@ -74,8 +74,7 @@ function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true,
{translate('common.cancel')}
)}
- {/* This is only temporary for development and will be cleaned up in: https://github.com/Expensify/App/issues/49122 */}
-
+ {shouldDisplaySearchRouter && }
{displaySearch && (
;
-
- const lastSearchRoute = rootState.routes.filter((route) => route.name === SCREENS.SEARCH.CENTRAL_PANE).at(-1);
-
- return lastSearchRoute ? (lastSearchRoute.params as AuthScreensParamList[typeof SCREENS.SEARCH.CENTRAL_PANE]) : undefined;
-}
-
function isSearchResultsEmpty(searchResults: SearchResults) {
return !Object.keys(searchResults?.data).some((key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION));
}
@@ -407,6 +397,20 @@ function getQueryHashFromString(query: SearchQueryString): number {
return UserUtils.hashText(query, 2 ** 32);
}
+function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths {
+ // eslint-disable-next-line default-case
+ switch (expenseType) {
+ case CONST.SEARCH.TRANSACTION_TYPE.DISTANCE:
+ return 'common.distance';
+ case CONST.SEARCH.TRANSACTION_TYPE.CARD:
+ return 'common.card';
+ case CONST.SEARCH.TRANSACTION_TYPE.CASH:
+ return 'iou.cash';
+ }
+}
+
+/* Search query related */
+
/**
* Update string query with all the default params that are set by parser
*/
@@ -467,16 +471,58 @@ function sanitizeString(str: string) {
return str;
}
-function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths {
- // eslint-disable-next-line default-case
- switch (expenseType) {
- case CONST.SEARCH.TRANSACTION_TYPE.DISTANCE:
- return 'common.distance';
- case CONST.SEARCH.TRANSACTION_TYPE.CARD:
- return 'common.card';
- case CONST.SEARCH.TRANSACTION_TYPE.CASH:
- return 'iou.cash';
+/**
+ * @private
+ * traverses the AST and returns filters as a QueryFilters object
+ */
+function getFilters(queryJSON: SearchQueryJSON) {
+ const filters = {} as QueryFilters;
+ const filterKeys = Object.values(CONST.SEARCH.SYNTAX_FILTER_KEYS);
+
+ function traverse(node: ASTNode) {
+ if (!node.operator) {
+ return;
+ }
+
+ if (typeof node?.left === 'object' && node.left) {
+ traverse(node.left);
+ }
+
+ if (typeof node?.right === 'object' && node.right && !Array.isArray(node.right)) {
+ traverse(node.right);
+ }
+
+ const nodeKey = node.left as ValueOf;
+ if (!filterKeys.includes(nodeKey)) {
+ return;
+ }
+
+ if (!filters[nodeKey]) {
+ filters[nodeKey] = [];
+ }
+
+ // the "?? []" is added only for typescript because otherwise TS throws an error, in newer TS versions this should be fixed
+ const filterArray = filters[nodeKey] ?? [];
+ if (!Array.isArray(node.right)) {
+ filterArray.push({
+ operator: node.operator,
+ value: node.right as string | number,
+ });
+ } else {
+ node.right.forEach((element) => {
+ filterArray.push({
+ operator: node.operator,
+ value: element as string | number,
+ });
+ });
+ }
}
+
+ if (queryJSON.filters) {
+ traverse(queryJSON.filters);
+ }
+
+ return filters;
}
function buildSearchQueryJSON(query: SearchQueryString) {
@@ -528,7 +574,7 @@ function buildSearchQueryString(queryJSON?: SearchQueryJSON) {
/**
* Given object with chosen search filters builds correct query string from them
*/
-function buildQueryStringFromFilterValues(filterValues: Partial) {
+function buildQueryStringFromFilterFormValues(filterValues: Partial) {
// We separate type and status filters from other filters to maintain hashes consistency for saved searches
const {type, status, ...otherFilters} = filterValues;
const filtersString: string[] = [];
@@ -592,65 +638,10 @@ function buildQueryStringFromFilterValues(filterValues: Partial;
- if (!filterKeys.includes(nodeKey)) {
- return;
- }
-
- if (!filters[nodeKey]) {
- filters[nodeKey] = [];
- }
-
- // the "?? []" is added only for typescript because otherwise TS throws an error, in newer TS versions this should be fixed
- const filterArray = filters[nodeKey] ?? [];
- if (!Array.isArray(node.right)) {
- filterArray.push({
- operator: node.operator,
- value: node.right as string | number,
- });
- } else {
- node.right.forEach((element) => {
- filterArray.push({
- operator: node.operator,
- value: element as string | number,
- });
- });
- }
- }
-
- if (queryJSON.filters) {
- traverse(queryJSON.filters);
- }
-
- return filters;
-}
-
/**
* returns the values of the filters in a format that can be used in the SearchAdvancedFiltersForm as initial form values
*/
-function getFiltersFormValues(queryJSON: SearchQueryJSON) {
+function buildFilterFormValuesFromQuery(queryJSON: SearchQueryJSON) {
const filters = getFilters(queryJSON);
const filterKeys = Object.keys(filters);
const filtersForm = {} as Partial;
@@ -827,14 +818,12 @@ function isCorrectSearchUserName(displayName?: string) {
}
export {
- buildQueryStringFromFilterValues,
+ buildQueryStringFromFilterFormValues,
buildSearchQueryJSON,
buildSearchQueryString,
- getCurrentSearchParams,
- getFiltersFormValues,
+ buildFilterFormValuesFromQuery,
getPolicyIDFromSearchQuery,
getListItem,
- getSearchHeaderTitle,
getSections,
getShouldShowMerchant,
getSortedSections,
@@ -842,6 +831,7 @@ export {
isSearchResultsEmpty,
isTransactionListItemType,
isReportActionListItemType,
+ getSearchHeaderTitle,
normalizeQuery,
shouldShowYear,
buildCannedSearchQuery,
diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index 88e52409751b..fc9ae171ccf5 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -85,6 +85,7 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
title={title}
shouldShowBackButton
onBackButtonPress={() => Navigation.goBack(backTo)}
+ shouldDisplaySearchRouter
/>
{isLoadingApp ? (
diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx
index 8f08b128619a..f2e3173c977a 100644
--- a/src/pages/Search/AdvancedSearchFilters.tsx
+++ b/src/pages/Search/AdvancedSearchFilters.tsx
@@ -229,7 +229,7 @@ function AdvancedSearchFilters() {
const personalDetails = usePersonalDetails();
const currentType = searchAdvancedFilters?.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE;
- const queryString = useMemo(() => SearchUtils.buildQueryStringFromFilterValues(searchAdvancedFilters) || '', [searchAdvancedFilters]);
+ const queryString = useMemo(() => SearchUtils.buildQueryStringFromFilterFormValues(searchAdvancedFilters) || '', [searchAdvancedFilters]);
const queryJSON = useMemo(() => SearchUtils.buildSearchQueryJSON(queryString || SearchUtils.buildCannedSearchQuery()) ?? ({} as SearchQueryJSON), [queryString]);
const applyFiltersAndNavigate = () => {
diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx
index 9226093154ae..7095413398b8 100644
--- a/src/pages/Search/SearchPageBottomTab.tsx
+++ b/src/pages/Search/SearchPageBottomTab.tsx
@@ -52,6 +52,7 @@ function SearchPageBottomTab() {
activeWorkspaceID={policyID}
breadcrumbLabel={translate('common.search')}
shouldDisplaySearch={false}
+ shouldDisplaySearchRouter={shouldUseNarrowLayout}
isCustomSearchQuery={shouldUseNarrowLayout && !SearchUtils.isCannedSearchQuery(queryJSON)}
/>
diff --git a/src/pages/Search/SearchTypeMenuNarrow.tsx b/src/pages/Search/SearchTypeMenuNarrow.tsx
index 0158a15bfc41..b5d390e2fc53 100644
--- a/src/pages/Search/SearchTypeMenuNarrow.tsx
+++ b/src/pages/Search/SearchTypeMenuNarrow.tsx
@@ -57,7 +57,7 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title,
const openMenu = useCallback(() => setIsPopoverVisible(true), []);
const closeMenu = useCallback(() => setIsPopoverVisible(false), []);
const onPress = () => {
- const values = SearchUtils.getFiltersFormValues(queryJSON);
+ const values = SearchUtils.buildFilterFormValuesFromQuery(queryJSON);
SearchActions.updateAdvancedFilters(values);
Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS);
};
diff --git a/src/pages/TeachersUnite/SaveTheWorldPage.tsx b/src/pages/TeachersUnite/SaveTheWorldPage.tsx
index b4f850981c92..b30fedab530e 100644
--- a/src/pages/TeachersUnite/SaveTheWorldPage.tsx
+++ b/src/pages/TeachersUnite/SaveTheWorldPage.tsx
@@ -56,6 +56,7 @@ function SaveTheWorldPage() {
Navigation.goBack()}
icon={Illustrations.TeachersUnite}
/>
diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx
index 14ed4b583baf..d7fdef7d11e7 100644
--- a/src/pages/home/HeaderView.tsx
+++ b/src/pages/home/HeaderView.tsx
@@ -13,6 +13,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import ReportHeaderSkeletonView from '@components/ReportHeaderSkeletonView';
+import SearchButton from '@components/Search/SearchRouter/SearchButton';
import SubscriptAvatar from '@components/SubscriptAvatar';
import TaskHeaderActionButton from '@components/TaskHeaderActionButton';
import Text from '@components/Text';
@@ -269,6 +270,7 @@ function HeaderView({report, parentReportAction, reportID, onNavigationMenuButto
{isTaskReport && !shouldUseNarrowLayout && ReportUtils.isOpenTaskReport(report, parentReportAction) && }
{canJoin && !shouldUseNarrowLayout && joinButton}
+
Navigation.goBack(ROUTES.SETTINGS)}
icon={Illustrations.PalmTree}
/>
diff --git a/src/pages/settings/Preferences/PreferencesPage.tsx b/src/pages/settings/Preferences/PreferencesPage.tsx
index e51250f3538a..f2c5f0366640 100755
--- a/src/pages/settings/Preferences/PreferencesPage.tsx
+++ b/src/pages/settings/Preferences/PreferencesPage.tsx
@@ -40,6 +40,7 @@ function PreferencesPage() {
title={translate('common.preferences')}
icon={Illustrations.Gears}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
onBackButtonPress={() => Navigation.goBack()}
/>
diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index 38dec5fe0647..46f280abf191 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -113,6 +113,7 @@ function ProfilePage() {
title={translate('common.profile')}
onBackButtonPress={() => Navigation.goBack()}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
icon={Illustrations.Profile}
/>
diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx
index 6403b0ac64e2..e54e7d873096 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.tsx
+++ b/src/pages/settings/Security/SecuritySettingsPage.tsx
@@ -141,6 +141,7 @@ function SecuritySettingsPage() {
shouldShowBackButton={shouldUseNarrowLayout}
onBackButtonPress={() => Navigation.goBack()}
icon={Illustrations.LockClosed}
+ shouldDisplaySearchRouter
/>
diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx
index ecc6a6cdc27a..2cb99207f8e0 100644
--- a/src/pages/settings/Subscription/CardSection/CardSection.tsx
+++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx
@@ -61,7 +61,7 @@ function CardSection() {
}, []);
const viewPurchases = useCallback(() => {
- const query = SearchUtils.buildQueryStringFromFilterValues({merchant: CONST.EXPENSIFY_MERCHANT});
+ const query = SearchUtils.buildQueryStringFromFilterFormValues({merchant: CONST.EXPENSIFY_MERCHANT});
Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query}));
}, []);
diff --git a/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx b/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
index 16fa481b16a6..c34db3fa77a8 100644
--- a/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
@@ -47,6 +47,7 @@ function SubscriptionSettingsPage() {
title={translate('workspace.common.subscription')}
onBackButtonPress={() => Navigation.goBack()}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
icon={Illustrations.CreditCardsNew}
/>
diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
index 79f7e45d8cda..d6d0489f7676 100644
--- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
+++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
@@ -1,7 +1,6 @@
import React, {useCallback, useMemo, useState} from 'react';
import {View} from 'react-native';
-import Onyx, {withOnyx} from 'react-native-onyx';
-import type {OnyxEntry} from 'react-native-onyx';
+import Onyx, {useOnyx} from 'react-native-onyx';
import type {SvgProps} from 'react-native-svg';
import ClientSideLoggingToolMenu from '@components/ClientSideLoggingToolMenu';
import ConfirmModal from '@components/ConfirmModal';
@@ -39,14 +38,7 @@ type BaseMenuItem = {
action: () => void | Promise;
};
-type TroubleshootPageOnyxProps = {
- shouldStoreLogs: OnyxEntry;
- shouldMaskOnyxState: boolean;
-};
-
-type TroubleshootPageProps = TroubleshootPageOnyxProps;
-
-function TroubleshootPage({shouldStoreLogs, shouldMaskOnyxState}: TroubleshootPageProps) {
+function TroubleshootPage() {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {isProduction} = useEnvironment();
@@ -55,6 +47,9 @@ function TroubleshootPage({shouldStoreLogs, shouldMaskOnyxState}: TroubleshootPa
const {shouldUseNarrowLayout} = useResponsiveLayout();
const illustrationStyle = getLightbulbIllustrationStyle();
+ const [shouldStoreLogs] = useOnyx(ONYXKEYS.SHOULD_STORE_LOGS);
+ const [shouldMaskOnyxState = true] = useOnyx(ONYXKEYS.SHOULD_MASK_ONYX_STATE);
+
const exportOnyxState = useCallback(() => {
ExportOnyxState.readFromOnyxDatabase().then((value: Record) => {
const dataToShare = ExportOnyxState.maskOnyxState(value, shouldMaskOnyxState);
@@ -106,6 +101,7 @@ function TroubleshootPage({shouldStoreLogs, shouldMaskOnyxState}: TroubleshootPa
Navigation.goBack(ROUTES.SETTINGS)}
icon={Illustrations.Lightbulb}
/>
@@ -176,12 +172,4 @@ function TroubleshootPage({shouldStoreLogs, shouldMaskOnyxState}: TroubleshootPa
TroubleshootPage.displayName = 'TroubleshootPage';
-export default withOnyx({
- shouldStoreLogs: {
- key: ONYXKEYS.SHOULD_STORE_LOGS,
- },
- shouldMaskOnyxState: {
- key: ONYXKEYS.SHOULD_MASK_ONYX_STATE,
- selector: (shouldMaskOnyxState) => shouldMaskOnyxState ?? true,
- },
-})(TroubleshootPage);
+export default TroubleshootPage;
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index cf13c29ffb20..3ef77458de11 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -367,6 +367,7 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
onBackButtonPress={() => Navigation.goBack()}
icon={Illustrations.MoneyIntoWallet}
shouldShowBackButton={shouldUseNarrowLayout}
+ shouldDisplaySearchRouter
/>
diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx
index c2a47e536d43..435c62bbe73d 100755
--- a/src/pages/workspace/WorkspacesListPage.tsx
+++ b/src/pages/workspace/WorkspacesListPage.tsx
@@ -1,7 +1,6 @@
import React, {useCallback, useMemo, useState} from 'react';
import {FlatList, View} from 'react-native';
-import {useOnyx, withOnyx} from 'react-native-onyx';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import Button from '@components/Button';
import ConfirmModal from '@components/ConfirmModal';
@@ -38,7 +37,7 @@ import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
-import type {Policy as PolicyType, ReimbursementAccount, Report, Session as SessionType} from '@src/types/onyx';
+import type {Policy as PolicyType} from '@src/types/onyx';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import WorkspacesListRow from './WorkspacesListRow';
@@ -67,22 +66,6 @@ type ChatType = {
type ChatPolicyType = Record;
-type WorkspaceListPageOnyxProps = {
- /** The list of this user's policies */
- policies: OnyxCollection;
-
- /** Bank account attached to free plan */
- reimbursementAccount: OnyxEntry;
-
- /** All reports shared with the user (coming from Onyx) */
- reports: OnyxCollection;
-
- /** Session info for the currently logged in user. */
- session: OnyxEntry;
-};
-
-type WorkspaceListPageProps = WorkspaceListPageOnyxProps;
-
const workspaceFeatures: FeatureListItem[] = [
{
icon: Illustrations.MoneyReceipts,
@@ -117,13 +100,17 @@ function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.Pendi
const stickyHeaderIndices = [0];
-function WorkspacesListPage({policies, reimbursementAccount, reports, session}: WorkspaceListPageProps) {
+function WorkspacesListPage() {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
const [allConnectionSyncProgresses] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS);
+ const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
+ const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
+ const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
+ const [session] = useOnyx(ONYXKEYS.SESSION);
const {activeWorkspaceID, setActiveWorkspaceID} = useActiveWorkspace();
@@ -313,7 +300,7 @@ function WorkspacesListPage({policies, reimbursementAccount, reports, session}:
}
return Object.values(policies)
- .filter((policy): policy is PolicyType => PolicyUtils.shouldShowPolicy(policy, !!isOffline, session?.email))
+ .filter((policy): policy is PolicyType => PolicyUtils.shouldShowPolicy(policy, isOffline, session?.email))
.map((policy): WorkspaceItem => {
if (policy?.isJoinRequestPending && policy?.policyDetailsForNonMembers) {
const policyInfo = Object.values(policy.policyDetailsForNonMembers)[0];
@@ -387,6 +374,7 @@ function WorkspacesListPage({policies, reimbursementAccount, reports, session}:
Navigation.goBack()}
icon={Illustrations.BigRocket}
>
@@ -423,6 +411,7 @@ function WorkspacesListPage({policies, reimbursementAccount, reports, session}:
Navigation.goBack()}
icon={Illustrations.BigRocket}
>
@@ -452,18 +441,4 @@ function WorkspacesListPage({policies, reimbursementAccount, reports, session}:
WorkspacesListPage.displayName = 'WorkspacesListPage';
-export default withOnyx({
- policies: {
- key: ONYXKEYS.COLLECTION.POLICY,
- },
- // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM
- reimbursementAccount: {
- key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
- },
- reports: {
- key: ONYXKEYS.COLLECTION.REPORT,
- },
- session: {
- key: ONYXKEYS.SESSION,
- },
-})(WorkspacesListPage);
+export default WorkspacesListPage;
diff --git a/tests/perf-test/ReportScreen.perf-test.tsx b/tests/perf-test/ReportScreen.perf-test.tsx
index 8b1d2d5de405..95ac9729e606 100644
--- a/tests/perf-test/ReportScreen.perf-test.tsx
+++ b/tests/perf-test/ReportScreen.perf-test.tsx
@@ -103,6 +103,7 @@ jest.mock('@src/hooks/useEnvironment', () =>
jest.mock('@src/libs/Permissions', () => ({
canUseLinkPreviews: jest.fn(() => true),
canUseDefaultRooms: jest.fn(() => true),
+ canUseNewSearchRouter: jest.fn(() => true),
}));
jest.mock('@src/libs/Navigation/Navigation', () => ({