From c96e51630fffd927b067c26ddd58b5104d79a54b Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Fri, 5 Apr 2024 06:26:34 +0200 Subject: [PATCH 01/26] migrate search page to find page v1 --- src/ROUTES.ts | 2 +- src/SCREENS.ts | 4 ++-- src/libs/E2E/tests/openSearchPageTest.e2e.ts | 2 +- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 2 +- .../AppNavigator/ModalStackNavigators/index.tsx | 6 +++--- .../AppNavigator/Navigators/LeftModalNavigator.tsx | 2 +- .../createCustomBottomTabNavigator/TopBar.tsx | 2 +- src/libs/Navigation/linkingConfig/config.ts | 4 ++-- src/libs/Navigation/types.ts | 10 +++++----- src/pages/SearchPage/index.tsx | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 8130c271a2db..0224270aa878 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -26,7 +26,7 @@ const ROUTES = { route: 'flag/:reportID/:reportActionID', getRoute: (reportID: string, reportActionID: string) => `flag/${reportID}/${reportActionID}` as const, }, - SEARCH: 'search', + FIND: 'find', DETAILS: { route: 'details', getRoute: (login: string) => `details?login=${encodeURIComponent(login)}` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index cf864fd96b3e..0006e243ee1e 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -93,7 +93,7 @@ const SCREENS = { ROOT: 'SaveTheWorld_Root', }, LEFT_MODAL: { - SEARCH: 'Search', + FIND: 'Find', WORKSPACE_SWITCHER: 'WorkspaceSwitcher', }, WORKSPACE_SWITCHER: { @@ -292,7 +292,7 @@ const SCREENS = { REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root', ROOM_MEMBERS_ROOT: 'RoomMembers_Root', ROOM_INVITE_ROOT: 'RoomInvite_Root', - SEARCH_ROOT: 'Search_Root', + FIND_ROOT: 'FIND_Root', FLAG_COMMENT_ROOT: 'FlagComment_Root', REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount', GET_ASSISTANCE: 'GetAssistance', diff --git a/src/libs/E2E/tests/openSearchPageTest.e2e.ts b/src/libs/E2E/tests/openSearchPageTest.e2e.ts index 86da851396f6..201cdc556d04 100644 --- a/src/libs/E2E/tests/openSearchPageTest.e2e.ts +++ b/src/libs/E2E/tests/openSearchPageTest.e2e.ts @@ -24,7 +24,7 @@ const test = () => { Performance.subscribeToMeasurements((entry) => { if (entry.name === CONST.TIMING.SIDEBAR_LOADED) { console.debug(`[E2E] Sidebar loaded, navigating to search routeā€¦`); - Navigation.navigate(ROUTES.SEARCH); + Navigation.navigate(ROUTES.FIND); return; } diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 463dcfcd9e99..c1d98d9e5e0e 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -232,7 +232,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie const unsubscribeSearchShortcut = KeyboardShortcut.subscribe( searchShortcutConfig.shortcutKey, () => { - Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.SEARCH))); + Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.FIND))); }, shortcutsOverviewShortcutConfig.descriptionKey, shortcutsOverviewShortcutConfig.modifiers, diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 0d1b9b59a089..a2afd3f9efcb 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -7,6 +7,7 @@ import type { DetailsNavigatorParamList, EditRequestNavigatorParamList, EnablePaymentsNavigatorParamList, + FindNavigatorParamList, FlagCommentNavigatorParamList, MoneyRequestNavigatorParamList, NewChatNavigatorParamList, @@ -22,7 +23,6 @@ import type { ReportSettingsNavigatorParamList, RoomInviteNavigatorParamList, RoomMembersNavigatorParamList, - SearchNavigatorParamList, SettingsNavigatorParamList, SignInNavigatorParamList, SplitDetailsNavigatorParamList, @@ -145,8 +145,8 @@ const RoomInviteModalStackNavigator = createModalStackNavigator require('../../../../pages/RoomInvitePage').default as React.ComponentType, }); -const SearchModalStackNavigator = createModalStackNavigator({ - [SCREENS.SEARCH_ROOT]: () => require('../../../../pages/SearchPage').default as React.ComponentType, +const SearchModalStackNavigator = createModalStackNavigator({ + [SCREENS.FIND_ROOT]: () => require('../../../../pages/SearchPage').default as React.ComponentType, }); const NewChatModalStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx index 8f76d8fbdd7b..28b72d662258 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx @@ -32,7 +32,7 @@ function LeftModalNavigator({navigation}: LeftModalNavigatorProps) { Navigation.navigate(ROUTES.SEARCH))} + onPress={Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.FIND))} > ['config'] = { [SCREENS.NOT_FOUND]: '*', [NAVIGATORS.LEFT_MODAL_NAVIGATOR]: { screens: { - [SCREENS.LEFT_MODAL.SEARCH]: { + [SCREENS.LEFT_MODAL.FIND]: { screens: { - [SCREENS.SEARCH_ROOT]: ROUTES.SEARCH, + [SCREENS.FIND_ROOT]: ROUTES.FIND, }, }, [SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index b88c44b9aa70..87ac410e3c01 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -281,8 +281,8 @@ type NewChatNavigatorParamList = { [SCREENS.NEW_CHAT.ROOT]: undefined; }; -type SearchNavigatorParamList = { - [SCREENS.SEARCH_ROOT]: undefined; +type FindNavigatorParamList = { + [SCREENS.FIND_ROOT]: undefined; }; type DetailsNavigatorParamList = { @@ -542,7 +542,7 @@ type PrivateNotesNavigatorParamList = { }; type LeftModalNavigatorParamList = { - [SCREENS.LEFT_MODAL.SEARCH]: NavigatorScreenParams; + [SCREENS.LEFT_MODAL.FIND]: NavigatorScreenParams; [SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER]: NavigatorScreenParams; }; @@ -700,7 +700,7 @@ type AuthScreensParamList = SharedScreensParamList & { }; }; -type RootStackParamList = PublicScreensParamList & AuthScreensParamList & SearchNavigatorParamList; +type RootStackParamList = PublicScreensParamList & AuthScreensParamList & FindNavigatorParamList; type BottomTabName = keyof BottomTabNavigatorParamList; @@ -742,7 +742,7 @@ export type { ParticipantsNavigatorParamList, RoomMembersNavigatorParamList, RoomInviteNavigatorParamList, - SearchNavigatorParamList, + FindNavigatorParamList, NewChatNavigatorParamList, NewTaskNavigatorParamList, TeachersUniteNavigatorParamList, diff --git a/src/pages/SearchPage/index.tsx b/src/pages/SearchPage/index.tsx index c072bfd56913..faad8200ac5e 100644 --- a/src/pages/SearchPage/index.tsx +++ b/src/pages/SearchPage/index.tsx @@ -34,7 +34,7 @@ type SearchPageOnyxProps = { isSearchingForReports: OnyxEntry; }; -type SearchPageProps = SearchPageOnyxProps & StackScreenProps; +type SearchPageProps = SearchPageOnyxProps & StackScreenProps; type SearchPageSectionItem = { data: OptionData[]; From 1e5150b624e19148436f84acc34cd0a1b3b68e2d Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Fri, 5 Apr 2024 14:01:29 +0200 Subject: [PATCH 02/26] add new search tab --- src/ROUTES.ts | 2 + src/SCREENS.ts | 2 + .../Navigators/BottomTabNavigator.tsx | 5 +++ .../BaseCentralPaneNavigator.tsx | 8 ++++ .../BottomTabBar.tsx | 27 ++++++++++++- .../createCustomStackNavigator/index.tsx | 40 +++++++++++++++---- src/libs/Navigation/linkTo.ts | 14 ++++++- .../TAB_TO_CENTRAL_PANE_MAPPING.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 1 + src/libs/Navigation/types.ts | 4 ++ src/pages/Search/SearchPage.tsx | 20 ++++++++++ src/pages/Search/SearchPageBottomTab.tsx | 15 +++++++ src/pages/SearchPage.tsx | 16 ++++++++ 13 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 src/pages/Search/SearchPage.tsx create mode 100644 src/pages/Search/SearchPageBottomTab.tsx create mode 100644 src/pages/SearchPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 0224270aa878..b6410c926f96 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -20,6 +20,8 @@ const ROUTES = { ALL_SETTINGS: 'all-settings', + SEARCH: 'search', + // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated CONCIERGE: 'concierge', FLAG_COMMENT: { diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 0006e243ee1e..55a067e02c97 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -13,6 +13,8 @@ const PROTECTED_SCREENS = { const SCREENS = { ...PROTECTED_SCREENS, ALL_SETTINGS: 'AllSettings', + SEARCH: 'Search', + SEARCH_BOTTOM_TAB: 'SearchBottomTab', REPORT: 'Report', PROFILE_AVATAR: 'ProfileAvatar', WORKSPACE_AVATAR: 'WorkspaceAvatar', diff --git a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx index 87a441f16ddb..93457a65ff3f 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx @@ -5,6 +5,7 @@ import createCustomBottomTabNavigator from '@libs/Navigation/AppNavigator/create import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; import type {BottomTabNavigatorParamList} from '@libs/Navigation/types'; import SidebarScreen from '@pages/home/sidebar/SidebarScreen'; +import SearchPageBottomTab from '@pages/Search/SearchPageBottomTab'; import SCREENS from '@src/SCREENS'; import ActiveRouteContext from './ActiveRouteContext'; @@ -27,6 +28,10 @@ function BottomTabNavigator() { name={SCREENS.HOME} component={SidebarScreen} /> + (); @@ -39,6 +40,13 @@ function BaseCentralPaneNavigator() { initialParams={{openOnAdminRoom: openOnAdminRoom === 'true' || undefined}} component={ReportScreenWrapper} /> + + {Object.entries(settingsScreens).map(([screenName, componentGetter]) => ( ((state) => { + const topmostCentralPaneRoute = getTopmostCentralPaneRoute(state); + + if (topmostCentralPaneRoute && topmostCentralPaneRoute.name === SCREENS.SEARCH) { + return SCREENS.SEARCH; + } + const topmostBottomTabRoute = getTopmostBottomTabRoute(state); return topmostBottomTabRoute?.name ?? SCREENS.HOME; }); @@ -83,10 +90,28 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps )} + { + Navigation.navigate(ROUTES.SEARCH); + }} + role={CONST.ROLE.BUTTON} + accessibilityLabel={translate('common.search')} + wrapperStyle={styles.flex1} + style={styles.bottomTabBarItem} + > + + + + - + ); } diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index 2a517c45eb0d..01e7743c1760 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -3,21 +3,25 @@ import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/na import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; import {StackView} from '@react-navigation/stack'; import React, {useEffect, useMemo} from 'react'; +import {View} from 'react-native'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; import navigationRef from '@libs/Navigation/navigationRef'; +import type {RootStackParamList, State} from '@libs/Navigation/types'; import NAVIGATORS from '@src/NAVIGATORS'; +import SCREENS from '@src/SCREENS'; import CustomRouter from './CustomRouter'; import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; type Routes = StackNavigationState['routes']; -function reduceReportRoutes(routes: Routes): Routes { +function reduceCentralPaneRoutes(routes: Routes): Routes { const result: Routes = []; let count = 0; const reverseRoutes = [...routes].reverse(); reverseRoutes.forEach((route) => { if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { - // Remove all report routes except the last 3. This will improve performance. + // Remove all central pane routes except the last 3. This will improve performance. if (count < 3) { result.push(route); count++; @@ -52,15 +56,34 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { navigationRef.resetRoot(navigationRef.getRootState()); }, [isSmallScreenWidth]); - const stateToRender = useMemo(() => { - const result = reduceReportRoutes(state.routes); + const {stateToRender, searchRoute} = useMemo(() => { + const routes = reduceCentralPaneRoutes(state.routes); + + const lastRoute = routes[routes.length - 1]; + const isLastRouteSearchRoute = getTopmostCentralPaneRoute({routes: [lastRoute]} as State)?.name === SCREENS.SEARCH; + + const firstRoute = routes[0]; + + if (isSmallScreenWidth && isLastRouteSearchRoute) { + return { + stateToRender: { + ...state, + index: 0, + routes: [firstRoute], + }, + searchRoute: lastRoute, + }; + } return { - ...state, - index: result.length - 1, - routes: [...result], + stateToRender: { + ...state, + index: routes.length - 1, + routes: [...routes], + }, + searchRoute: undefined, }; - }, [state]); + }, [state, isSmallScreenWidth]); return ( @@ -71,6 +94,7 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { descriptors={descriptors} navigation={navigation} /> + {searchRoute && {descriptors[searchRoute.key].render()}} ); } diff --git a/src/libs/Navigation/linkTo.ts b/src/libs/Navigation/linkTo.ts index afa8fb56069a..35b3460361c9 100644 --- a/src/libs/Navigation/linkTo.ts +++ b/src/libs/Navigation/linkTo.ts @@ -6,6 +6,7 @@ import {extractPolicyIDFromPath, getPathWithoutPolicyID} from '@libs/PolicyUtils import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; import type {Route} from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; import getActionsFromPartialDiff from './AppNavigator/getActionsFromPartialDiff'; import getPartialStateDiff from './AppNavigator/getPartialStateDiff'; import dismissModal from './dismissModal'; @@ -152,6 +153,15 @@ export default function linkTo(navigation: NavigationContainerRef = { [SCREENS.HOME]: [SCREENS.REPORT], + [SCREENS.SEARCH_BOTTOM_TAB]: [SCREENS.SEARCH], [SCREENS.SETTINGS.ROOT]: [ SCREENS.SETTINGS.PROFILE.ROOT, SCREENS.SETTINGS.PREFERENCES.ROOT, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 729aaa3e7c54..9ba599874ba1 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -61,6 +61,7 @@ const config: LinkingOptions['config'] = { exact: true, }, [SCREENS.SETTINGS.WORKSPACES]: ROUTES.SETTINGS_WORKSPACES, + [SCREENS.SEARCH]: ROUTES.SEARCH, }, }, [SCREENS.NOT_FOUND]: '*', diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 87ac410e3c01..a2e8bbef4c22 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -59,6 +59,9 @@ type CentralPaneNavigatorParamList = { [SCREENS.SETTINGS.WALLET.ROOT]: undefined; [SCREENS.SETTINGS.ABOUT]: undefined; [SCREENS.SETTINGS.WORKSPACES]: undefined; + [SCREENS.SEARCH]: { + filter: string; + }; }; type WorkspaceSwitcherNavigatorParamList = { @@ -636,6 +639,7 @@ type FullScreenNavigatorParamList = { type BottomTabNavigatorParamList = { [SCREENS.HOME]: undefined; + [SCREENS.SEARCH_BOTTOM_TAB]: undefined; [SCREENS.SETTINGS.ROOT]: undefined; }; diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx new file mode 100644 index 000000000000..22725453ea9a --- /dev/null +++ b/src/pages/Search/SearchPage.tsx @@ -0,0 +1,20 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {Text} from 'react-native'; +import ScreenWrapper from '@components/ScreenWrapper'; +import type {CentralPaneNavigatorParamList} from '@libs/Navigation/types'; +import type SCREENS from '@src/SCREENS'; + +type SearchPageProps = StackScreenProps; + +function SearchPage({route}: SearchPageProps) { + return ( + + Search page |{route.params.filter}| + + ); +} + +SearchPage.displayName = 'SearchPage'; + +export default SearchPage; diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx new file mode 100644 index 000000000000..65e13bf870c4 --- /dev/null +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import {Text} from 'react-native'; +import ScreenWrapper from '@components/ScreenWrapper'; + +function SearchPage() { + return ( + + Search page BOTTOM TAB + + ); +} + +SearchPage.displayName = 'SearchPage'; + +export default SearchPage; diff --git a/src/pages/SearchPage.tsx b/src/pages/SearchPage.tsx new file mode 100644 index 000000000000..76f81697d190 --- /dev/null +++ b/src/pages/SearchPage.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +// eslint-disable-next-line no-restricted-imports +import {Text} from 'react-native'; +import ScreenWrapper from '@components/ScreenWrapper'; + +function TestPage() { + return ( + + TEST PAGE + + ); +} + +TestPage.displayName = 'TestPage'; + +export default TestPage; From eef26cc858497cac3f2d1412f73049a998c5febe Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Mon, 8 Apr 2024 08:34:57 +0200 Subject: [PATCH 03/26] Add search page template components --- src/CONST.ts | 8 ++ src/ROUTES.ts | 5 + src/components/TabSelector/TabSelector.tsx | 10 ++ src/pages/Search/SearchPage.tsx | 4 +- src/pages/Search/SearchPageBottomTab.tsx | 111 +++++++++++++++++++-- src/pages/Search/SearchResults.tsx | 14 +++ 6 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 src/pages/Search/SearchResults.tsx diff --git a/src/CONST.ts b/src/CONST.ts index e7358b382f14..c90d9b4c3c4b 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3194,12 +3194,20 @@ const CONST = { NEW_ROOM: 'room', RECEIPT_TAB_ID: 'ReceiptTab', IOU_REQUEST_TYPE: 'iouRequestType', + SEARCH: 'search', }, TAB_REQUEST: { MANUAL: 'manual', SCAN: 'scan', DISTANCE: 'distance', }, + TAB_SEARCH: { + ALL: 'all', + SENT: 'sent', + DRAFTS: 'drafts', + WAITING_ON_YOU: 'waitingOnYou', + FINISHED: 'finished', + }, STATUS_TEXT_MAX_LENGTH: 100, DROPDOWN_BUTTON_SIZE: { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index b6410c926f96..130485925328 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -22,6 +22,11 @@ const ROUTES = { SEARCH: 'search', + SEARCH_WITH_FILTER: { + route: 'search?', + getRoute: (tab: string) => `search?filter=${tab}` as const, + }, + // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated CONCIERGE: 'concierge', FLAG_COMMENT: { diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index fc19e6a8062e..00ecd41beb08 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -33,6 +33,16 @@ function getIconAndTitle(route: string, translate: LocaleContextProps['translate return {icon: Expensicons.Hashtag, title: translate('tabSelector.room')}; case CONST.TAB_REQUEST.DISTANCE: return {icon: Expensicons.Car, title: translate('common.distance')}; + case CONST.TAB_SEARCH.ALL: + return {icon: Expensicons.ExpensifyLogoNew, title: 'All'}; + case CONST.TAB_SEARCH.SENT: + return {icon: Expensicons.ExpensifyLogoNew, title: 'Sent'}; + case CONST.TAB_SEARCH.DRAFTS: + return {icon: Expensicons.ExpensifyLogoNew, title: 'Drafts'}; + case CONST.TAB_SEARCH.WAITING_ON_YOU: + return {icon: Expensicons.ExpensifyLogoNew, title: 'Waiting on you'}; + case CONST.TAB_SEARCH.FINISHED: + return {icon: Expensicons.ExpensifyLogoNew, title: 'Finished'}; default: throw new Error(`Route ${route} has no icon nor title set.`); } diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 22725453ea9a..2decf6f96fe8 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -1,16 +1,16 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React from 'react'; -import {Text} from 'react-native'; import ScreenWrapper from '@components/ScreenWrapper'; import type {CentralPaneNavigatorParamList} from '@libs/Navigation/types'; import type SCREENS from '@src/SCREENS'; +import SearchResults from './SearchResults'; type SearchPageProps = StackScreenProps; function SearchPage({route}: SearchPageProps) { return ( - Search page |{route.params.filter}| + ); } diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index 65e13bf870c4..5267a4396ac0 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -1,15 +1,114 @@ -import React from 'react'; -import {Text} from 'react-native'; +import {useNavigationState} from '@react-navigation/native'; +import {StackScreenProps} from '@react-navigation/stack'; +import React, {useState} from 'react'; +import {Text, View} from 'react-native'; +import MenuItem from '@components/MenuItem'; import ScreenWrapper from '@components/ScreenWrapper'; +import TabSelector from '@components/TabSelector/TabSelector'; +import useSingleExecution from '@hooks/useSingleExecution'; +import useThemeStyles from '@hooks/useThemeStyles'; +import useWaitForNavigation from '@hooks/useWaitForNavigation'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; +import Navigation from '@libs/Navigation/Navigation'; +import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator'; +import type {CentralPaneNavigatorParamList, RootStackParamList} from '@libs/Navigation/types'; +import * as Expensicons from '@src/components/Icon/Expensicons'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import IconAsset from '@src/types/utils/IconAsset'; +import SearchPage from './SearchPage'; +import SearchResults from './SearchResults'; + +type SearchMenuItem = { + title: string; + icon: IconAsset; + action: () => void; +}; + +function SearchPageBottomTab() { + const styles = useThemeStyles(); + const {singleExecution} = useSingleExecution(); + const {isSmallScreenWidth} = useWindowDimensions(); + const waitForNavigate = useWaitForNavigation(); + + const [filter, setFilter] = useState('all'); + + const searchMenuItems: SearchMenuItem[] = [ + { + title: 'All', + icon: Expensicons.ExpensifyLogoNew, + action: singleExecution( + waitForNavigate(() => { + setFilter('all'); + Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('all')); + }), + ), + }, + { + title: 'Sent', + icon: Expensicons.ExpensifyLogoNew, + action: singleExecution( + waitForNavigate(() => { + setFilter('sent'); + Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('sent')); + }), + ), + }, + { + title: 'Drafts', + icon: Expensicons.ExpensifyLogoNew, + action: singleExecution( + waitForNavigate(() => { + setFilter('drafts'); + Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('drafts')); + }), + ), + }, + ]; -function SearchPage() { return ( - Search page BOTTOM TAB + {isSmallScreenWidth ? ( + { + setFilter(tab); + Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute(tab)); + }} + > + {() => } + {() => } + {() => } + + ) : ( + + {/* + Ideally we should use MenuList component for MenuItems with singleExecution/Navigation actions. + In this case where user can click on workspace avatar or menu items, we need to have a check for `isExecuting`. So, we are directly mapping menuItems. + */} + {searchMenuItems.map((item) => ( + + ))} + + )} ); } -SearchPage.displayName = 'SearchPage'; +SearchPageBottomTab.displayName = 'SearchPage'; -export default SearchPage; +export default SearchPageBottomTab; diff --git a/src/pages/Search/SearchResults.tsx b/src/pages/Search/SearchResults.tsx new file mode 100644 index 000000000000..b0d4c3bede39 --- /dev/null +++ b/src/pages/Search/SearchResults.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import Text from '@components/Text'; + +type SearchResultsProps = { + filter: string; +}; + +function SearchResults({filter}: SearchResultsProps) { + return Search results for: |{filter}| filter; +} + +SearchResults.displayName = 'SearchResults'; + +export default SearchResults; From 3c745077bf7c973f50d7a1957023bfec5bbf2d12 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 9 Apr 2024 18:14:04 +0200 Subject: [PATCH 04/26] Add new search pages --- src/ROUTES.ts | 11 ++++-- src/SCREENS.ts | 8 +++- .../ModalStackNavigators/index.tsx | 6 +++ .../Navigators/BottomTabNavigator.tsx | 2 +- .../BaseCentralPaneNavigator.tsx | 3 +- .../Navigators/RightModalNavigator.tsx | 4 ++ .../BottomTabBar.tsx | 8 ++-- .../index.native.tsx | 38 ++++++++++++++++++- .../createCustomStackNavigator/index.tsx | 2 +- .../CENTRAL_PANE_TO_RHP_MAPPING.ts | 1 + .../TAB_TO_CENTRAL_PANE_MAPPING.ts | 2 +- src/libs/Navigation/linkingConfig/config.ts | 7 +++- src/libs/Navigation/types.ts | 15 ++++++-- src/pages/Search/SearchPage.tsx | 2 +- src/pages/Search/SearchPageBottomTab.tsx | 8 ++-- src/pages/home/ReportScreen.tsx | 3 +- tests/perf-test/SearchPage.perf-test.tsx | 2 +- 17 files changed, 94 insertions(+), 28 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 130485925328..5d6175a275ea 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -20,11 +20,14 @@ const ROUTES = { ALL_SETTINGS: 'all-settings', - SEARCH: 'search', + SEARCH: { + route: '/search/:query', + getRoute: (query: string) => `search/${query}` as const, + }, - SEARCH_WITH_FILTER: { - route: 'search?', - getRoute: (tab: string) => `search?filter=${tab}` as const, + SEARCH_REPORT: { + route: '/search/:query/view/:reportID', + getRoute: (query: string, reportID: string) => `search/${query}/view/${reportID}` as const, }, // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 55a067e02c97..035deb85f9e1 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -13,8 +13,6 @@ const PROTECTED_SCREENS = { const SCREENS = { ...PROTECTED_SCREENS, ALL_SETTINGS: 'AllSettings', - SEARCH: 'Search', - SEARCH_BOTTOM_TAB: 'SearchBottomTab', REPORT: 'Report', PROFILE_AVATAR: 'ProfileAvatar', WORKSPACE_AVATAR: 'WorkspaceAvatar', @@ -25,6 +23,11 @@ const SCREENS = { UNLINK_LOGIN: 'UnlinkLogin', SETTINGS_CENTRAL_PANE: 'SettingsCentralPane', WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane', + SEARCH: { + CENTRAL_PANE: 'Search_Central_Pane', + REPORT: 'Search_Report', + BOTTOM_TAB: 'Search_Bottom_Tab', + }, SETTINGS: { ROOT: 'Settings_Root', SHARE_CODE: 'Settings_Share_Code', @@ -127,6 +130,7 @@ const SCREENS = { ROOM_INVITE: 'RoomInvite', REFERRAL: 'Referral', PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold', + SEARCH_REPORT: 'Search_Report', }, SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index a2afd3f9efcb..628497a1936d 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -23,6 +23,7 @@ import type { ReportSettingsNavigatorParamList, RoomInviteNavigatorParamList, RoomMembersNavigatorParamList, + SearchReportParamList, SettingsNavigatorParamList, SignInNavigatorParamList, SplitDetailsNavigatorParamList, @@ -149,6 +150,10 @@ const SearchModalStackNavigator = createModalStackNavigator require('../../../../pages/SearchPage').default as React.ComponentType, }); +const SearchReportModalStackNavigator = createModalStackNavigator({ + [SCREENS.SEARCH.REPORT]: () => require('../../../../pages/home/ReportScreen').default as React.ComponentType, +}); + const NewChatModalStackNavigator = createModalStackNavigator({ [SCREENS.NEW_CHAT.ROOT]: () => require('../../../../pages/NewChatSelectorPage').default as React.ComponentType, [SCREENS.NEW_CHAT.NEW_CHAT_CONFIRM]: () => require('../../../../pages/NewChatConfirmPage').default as React.ComponentType, @@ -342,4 +347,5 @@ export { WalletStatementStackNavigator, ProcessMoneyRequestHoldStackNavigator, WorkspaceSettingsModalStackNavigator, + SearchReportModalStackNavigator, }; diff --git a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx index 93457a65ff3f..7f18b54c4ac5 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx @@ -29,7 +29,7 @@ function BottomTabNavigator() { component={SidebarScreen} /> {Object.entries(settingsScreens).map(([screenName, componentGetter]) => ( diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index c421bdc82028..3d3fb569f69f 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -137,6 +137,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) { name="ProcessMoneyRequestHold" component={ModalStackNavigators.ProcessMoneyRequestHoldStackNavigator} /> + diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index 143bb7936057..84138929b05d 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -56,8 +56,8 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps const currentTabName = useNavigationState((state) => { const topmostCentralPaneRoute = getTopmostCentralPaneRoute(state); - if (topmostCentralPaneRoute && topmostCentralPaneRoute.name === SCREENS.SEARCH) { - return SCREENS.SEARCH; + if (topmostCentralPaneRoute && topmostCentralPaneRoute.name === SCREENS.SEARCH.CENTRAL_PANE) { + return SCREENS.SEARCH.CENTRAL_PANE; } const topmostBottomTabRoute = getTopmostBottomTabRoute(state); @@ -92,7 +92,7 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps { - Navigation.navigate(ROUTES.SEARCH); + Navigation.navigate(ROUTES.SEARCH.getRoute('all')); }} role={CONST.ROLE.BUTTON} accessibilityLabel={translate('common.search')} @@ -102,7 +102,7 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx index 151dd0a0f893..52d63e9bda26 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx @@ -2,8 +2,12 @@ import type {ParamListBase, StackActionHelpers, StackNavigationState} from '@rea import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; import {StackView} from '@react-navigation/stack'; -import React, {useRef} from 'react'; +import React, {useMemo, useRef} from 'react'; +import {View} from 'react-native'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; +import type {RootStackParamList, State} from '@libs/Navigation/types'; +import SCREENS from '@src/SCREENS'; import CustomRouter from './CustomRouter'; import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; @@ -26,15 +30,45 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { initialRouteName: props.initialRouteName, }); + const {stateToRender, searchRoute} = useMemo(() => { + const routes = state.routes; + + const lastRoute = routes[routes.length - 1]; + const isLastRouteSearchRoute = getTopmostCentralPaneRoute({routes: [lastRoute]} as State)?.name === SCREENS.SEARCH.CENTRAL_PANE; + + const firstRoute = routes[0]; + + if (isLastRouteSearchRoute) { + return { + stateToRender: { + ...state, + index: 0, + routes: [firstRoute], + }, + searchRoute: lastRoute, + }; + } + + return { + stateToRender: { + ...state, + index: routes.length - 1, + routes: [...routes], + }, + searchRoute: undefined, + }; + }, [state]); + return ( + {searchRoute && {descriptors[searchRoute.key].render()}} ); } diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index 01e7743c1760..767190bb1967 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -60,7 +60,7 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { const routes = reduceCentralPaneRoutes(state.routes); const lastRoute = routes[routes.length - 1]; - const isLastRouteSearchRoute = getTopmostCentralPaneRoute({routes: [lastRoute]} as State)?.name === SCREENS.SEARCH; + const isLastRouteSearchRoute = getTopmostCentralPaneRoute({routes: [lastRoute]} as State)?.name === SCREENS.SEARCH.CENTRAL_PANE; const firstRoute = routes[0]; diff --git a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts index 95233bfed079..5d2c3ab9d1d1 100755 --- a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts @@ -36,6 +36,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial> = ], [SCREENS.SETTINGS.SECURITY]: [SCREENS.SETTINGS.TWO_FACTOR_AUTH, SCREENS.SETTINGS.CLOSE], [SCREENS.SETTINGS.ABOUT]: [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS, SCREENS.SETTINGS.TROUBLESHOOT], + [SCREENS.SEARCH.CENTRAL_PANE]: [SCREENS.SEARCH.REPORT], }; export default CENTRAL_PANE_TO_RHP_MAPPING; diff --git a/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts b/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts index efda5da092a5..efd0a1ae756d 100755 --- a/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts @@ -3,7 +3,7 @@ import SCREENS from '@src/SCREENS'; const TAB_TO_CENTRAL_PANE_MAPPING: Record = { [SCREENS.HOME]: [SCREENS.REPORT], - [SCREENS.SEARCH_BOTTOM_TAB]: [SCREENS.SEARCH], + [SCREENS.SEARCH.BOTTOM_TAB]: [SCREENS.SEARCH.CENTRAL_PANE], [SCREENS.SETTINGS.ROOT]: [ SCREENS.SETTINGS.PROFILE.ROOT, SCREENS.SETTINGS.PREFERENCES.ROOT, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 9ba599874ba1..8f1e50ce9a2b 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -61,7 +61,7 @@ const config: LinkingOptions['config'] = { exact: true, }, [SCREENS.SETTINGS.WORKSPACES]: ROUTES.SETTINGS_WORKSPACES, - [SCREENS.SEARCH]: ROUTES.SEARCH, + [SCREENS.SEARCH.CENTRAL_PANE]: ROUTES.SEARCH.route, }, }, [SCREENS.NOT_FOUND]: '*', @@ -593,6 +593,11 @@ const config: LinkingOptions['config'] = { [SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: ROUTES.PROCESS_MONEY_REQUEST_HOLD, }, }, + [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: { + screens: { + [SCREENS.SEARCH.REPORT]: ROUTES.SEARCH_REPORT.route, + }, + }, }, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index a2e8bbef4c22..bed1a4b555ad 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -59,8 +59,8 @@ type CentralPaneNavigatorParamList = { [SCREENS.SETTINGS.WALLET.ROOT]: undefined; [SCREENS.SETTINGS.ABOUT]: undefined; [SCREENS.SETTINGS.WORKSPACES]: undefined; - [SCREENS.SEARCH]: { - filter: string; + [SCREENS.SEARCH.CENTRAL_PANE]: { + query: string; }; }; @@ -549,6 +549,13 @@ type LeftModalNavigatorParamList = { [SCREENS.LEFT_MODAL.WORKSPACE_SWITCHER]: NavigatorScreenParams; }; +type SearchReportParamList = { + [SCREENS.SEARCH.REPORT]: { + query: string; + reportID: string; + }; +}; + type RightModalNavigatorParamList = { [SCREENS.RIGHT_MODAL.SETTINGS]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.NEW_CHAT]: NavigatorScreenParams; @@ -576,6 +583,7 @@ type RightModalNavigatorParamList = { [SCREENS.RIGHT_MODAL.PROCESS_MONEY_REQUEST_HOLD]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams; }; type WorkspacesCentralPaneNavigatorParamList = { @@ -639,7 +647,7 @@ type FullScreenNavigatorParamList = { type BottomTabNavigatorParamList = { [SCREENS.HOME]: undefined; - [SCREENS.SEARCH_BOTTOM_TAB]: undefined; + [SCREENS.SEARCH.BOTTOM_TAB]: undefined; [SCREENS.SETTINGS.ROOT]: undefined; }; @@ -767,4 +775,5 @@ export type { FullScreenNavigatorParamList, WorkspacesCentralPaneNavigatorParamList, BackToParams, + SearchReportParamList, }; diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 2decf6f96fe8..488ce1dbb28a 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -10,7 +10,7 @@ type SearchPageProps = StackScreenProps - + ); } diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index 5267a4396ac0..cc108010cb55 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -42,7 +42,7 @@ function SearchPageBottomTab() { action: singleExecution( waitForNavigate(() => { setFilter('all'); - Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('all')); + Navigation.navigate(ROUTES.SEARCH.getRoute('all')); }), ), }, @@ -52,7 +52,7 @@ function SearchPageBottomTab() { action: singleExecution( waitForNavigate(() => { setFilter('sent'); - Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('sent')); + Navigation.navigate(ROUTES.SEARCH.getRoute('sent')); }), ), }, @@ -62,7 +62,7 @@ function SearchPageBottomTab() { action: singleExecution( waitForNavigate(() => { setFilter('drafts'); - Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute('drafts')); + Navigation.navigate(ROUTES.SEARCH.getRoute('drafts')); }), ), }, @@ -76,7 +76,7 @@ function SearchPageBottomTab() { tabBar={TabSelector} onTabSelected={(tab: string) => { setFilter(tab); - Navigation.navigate(ROUTES.SEARCH_WITH_FILTER.getRoute(tab)); + Navigation.navigate(ROUTES.SEARCH.getRoute(tab)); }} > {() => } diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index ef277984b4e9..d2833a4a77f9 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -356,7 +356,8 @@ function ReportScreen({ return reportIDFromRoute !== '' && !!report.reportID && !isTransitioning; }, [report, reportIDFromRoute]); - const isLoading = !ReportUtils.isValidReportIDFromPath(reportIDFromRoute) || !isSidebarLoaded || PersonalDetailsUtils.isPersonalDetailsEmpty(); + // @TODO: isSidebarLoaded has been removed from isLoading variable to prevent from infinite loading on SCREENS.SEARCH.REPORT. Remember to undo this change and handle this case + const isLoading = !ReportUtils.isValidReportIDFromPath(reportIDFromRoute) || PersonalDetailsUtils.isPersonalDetailsEmpty(); const shouldShowSkeleton = !isLinkedMessageAvailable && (isLinkingToMessage || diff --git a/tests/perf-test/SearchPage.perf-test.tsx b/tests/perf-test/SearchPage.perf-test.tsx index 95f5630e3fe9..bb2d31987f8e 100644 --- a/tests/perf-test/SearchPage.perf-test.tsx +++ b/tests/perf-test/SearchPage.perf-test.tsx @@ -119,7 +119,7 @@ afterEach(() => { PusherHelper.teardown(); }); -type SearchPageProps = StackScreenProps & { +type SearchPageProps = StackScreenProps & { betas: OnyxEntry; reports: OnyxCollection; isSearchingForReports: OnyxEntry; From a707c28b009c773b7d1b16903beb69472d5f783d Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 11:40:41 +0200 Subject: [PATCH 05/26] remove native.tsx for createCustomStackNavigator --- .../index.native.tsx | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx deleted file mode 100644 index 151dd0a0f893..000000000000 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import type {ParamListBase, StackActionHelpers, StackNavigationState} from '@react-navigation/native'; -import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; -import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; -import {StackView} from '@react-navigation/stack'; -import React, {useRef} from 'react'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import CustomRouter from './CustomRouter'; -import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; - -function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { - const {isSmallScreenWidth} = useWindowDimensions(); - - const isSmallScreenWidthRef = useRef(isSmallScreenWidth); - - isSmallScreenWidthRef.current = isSmallScreenWidth; - - const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder< - StackNavigationState, - ResponsiveStackNavigatorRouterOptions, - StackActionHelpers, - StackNavigationOptions, - StackNavigationEventMap - >(CustomRouter, { - children: props.children, - screenOptions: props.screenOptions, - initialRouteName: props.initialRouteName, - }); - - return ( - - - - ); -} - -ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; - -export default createNavigatorFactory, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator); From 3afd0b9251871e4ca87bec16ced4b126e117ddbe Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 11:41:10 +0200 Subject: [PATCH 06/26] add check for search page in getAdaptedStateFromPath --- src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts index 3cdcfba59466..5f5e023639b0 100644 --- a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts +++ b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts @@ -302,7 +302,9 @@ function getAdaptedState(state: PartialState // Routes // - found bottom tab // - matching central pane on desktop layout - if (isNarrowLayout) { + + // We want to make sure that the bottom tab search page is always pushed with matching central pane page. Even on the narrow layout. + if (isNarrowLayout && bottomTabNavigator.state?.routes[0].name !== SCREENS.SEARCH_BOTTOM_TAB) { return { adaptedState: state, metainfo, From 2206c1d61b5bb091869517d8a84898472fd3d363 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 10 Apr 2024 11:55:35 +0200 Subject: [PATCH 07/26] Handle passing params to useActiveRoute --- src/hooks/useActiveRoute.ts | 3 +- .../Navigators/ActiveRouteContext.ts | 3 +- .../Navigators/BottomTabNavigator.tsx | 2 +- src/pages/Search/SearchPageBottomTab.tsx | 43 +++++-------------- src/pages/settings/InitialSettingsPage.tsx | 4 +- 5 files changed, 18 insertions(+), 37 deletions(-) diff --git a/src/hooks/useActiveRoute.ts b/src/hooks/useActiveRoute.ts index 651d00a0c37c..afccc28f8243 100644 --- a/src/hooks/useActiveRoute.ts +++ b/src/hooks/useActiveRoute.ts @@ -1,7 +1,8 @@ import {useContext} from 'react'; import ActiveRouteContext from '@libs/Navigation/AppNavigator/Navigators/ActiveRouteContext'; +import type {CentralPaneNavigatorParamList, NavigationPartialRoute} from '@libs/Navigation/types'; -function useActiveRoute(): string { +function useActiveRoute(): NavigationPartialRoute | undefined { return useContext(ActiveRouteContext); } diff --git a/src/libs/Navigation/AppNavigator/Navigators/ActiveRouteContext.ts b/src/libs/Navigation/AppNavigator/Navigators/ActiveRouteContext.ts index d1d14d43af1a..6d0de3211e7c 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/ActiveRouteContext.ts +++ b/src/libs/Navigation/AppNavigator/Navigators/ActiveRouteContext.ts @@ -1,5 +1,6 @@ import React from 'react'; +import type {CentralPaneNavigatorParamList, NavigationPartialRoute} from '@libs/Navigation/types'; -const ActiveRouteContext = React.createContext(''); +const ActiveRouteContext = React.createContext | undefined>(undefined); export default ActiveRouteContext; diff --git a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx index 7f18b54c4ac5..6680ea302441 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx @@ -22,7 +22,7 @@ function BottomTabNavigator() { const activeRoute = useNavigationState(getTopmostCentralPaneRoute); return ( - + { - setFilter('all'); - Navigation.navigate(ROUTES.SEARCH.getRoute('all')); - }), - ), + action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('all')))), }, { title: 'Sent', icon: Expensicons.ExpensifyLogoNew, - action: singleExecution( - waitForNavigate(() => { - setFilter('sent'); - Navigation.navigate(ROUTES.SEARCH.getRoute('sent')); - }), - ), + action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('sent')))), }, { title: 'Drafts', icon: Expensicons.ExpensifyLogoNew, - action: singleExecution( - waitForNavigate(() => { - setFilter('drafts'); - Navigation.navigate(ROUTES.SEARCH.getRoute('drafts')); - }), - ), + action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('drafts')))), }, ]; @@ -74,10 +54,7 @@ function SearchPageBottomTab() { { - setFilter(tab); - Navigation.navigate(ROUTES.SEARCH.getRoute(tab)); - }} + onTabSelected={(tab: string) => Navigation.navigate(ROUTES.SEARCH.getRoute(tab))} > {() => } {() => } @@ -98,7 +75,7 @@ function SearchPageBottomTab() { icon={item.icon} onPress={item.action} wrapperStyle={styles.sectionMenuItem} - focused={item.title.toLowerCase() === filter} + focused={item.title.toLowerCase() === currentQuery} hoverAndPressStyle={styles.hoveredComponentBG} isPaneMenu /> diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 73bd031b5978..7397020448e5 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -319,7 +319,9 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa hoverAndPressStyle={styles.hoveredComponentBG} shouldBlockSelection={Boolean(item.link)} onSecondaryInteraction={item.link ? (event) => openPopover(item.link, event) : undefined} - focused={!!activeRoute && !!item.routeName && !!(activeRoute.toLowerCase().replaceAll('_', '') === item.routeName.toLowerCase().replaceAll('/', ''))} + focused={ + !!activeRoute?.name && !!item.routeName && !!(activeRoute?.name.toLowerCase().replaceAll('_', '') === item.routeName.toLowerCase().replaceAll('/', '')) + } isPaneMenu iconRight={item.iconRight} shouldShowRightIcon={item.shouldShowRightIcon} From a1b228a1ee762d6303f60de945a6aa22e1f5ac9e Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 10 Apr 2024 12:41:13 +0200 Subject: [PATCH 08/26] Adjust getAdaptedStateFromPath to new search routes --- src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts index 5f5e023639b0..8df528efa792 100644 --- a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts +++ b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts @@ -304,7 +304,7 @@ function getAdaptedState(state: PartialState // - matching central pane on desktop layout // We want to make sure that the bottom tab search page is always pushed with matching central pane page. Even on the narrow layout. - if (isNarrowLayout && bottomTabNavigator.state?.routes[0].name !== SCREENS.SEARCH_BOTTOM_TAB) { + if (isNarrowLayout && bottomTabNavigator.state?.routes[0].name !== SCREENS.SEARCH.BOTTOM_TAB) { return { adaptedState: state, metainfo, From a72d2217e7a0bf7f4a9b9e6515a18fce49f60cd5 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 17:10:29 +0200 Subject: [PATCH 09/26] fix linnkTo --- src/libs/Navigation/linkTo.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libs/Navigation/linkTo.ts b/src/libs/Navigation/linkTo.ts index 35b3460361c9..630a44fe1d3b 100644 --- a/src/libs/Navigation/linkTo.ts +++ b/src/libs/Navigation/linkTo.ts @@ -6,7 +6,6 @@ import {extractPolicyIDFromPath, getPathWithoutPolicyID} from '@libs/PolicyUtils import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; import type {Route} from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; import getActionsFromPartialDiff from './AppNavigator/getActionsFromPartialDiff'; import getPartialStateDiff from './AppNavigator/getPartialStateDiff'; import dismissModal from './dismissModal'; @@ -14,7 +13,6 @@ import getPolicyIDFromState from './getPolicyIDFromState'; import getStateFromPath from './getStateFromPath'; import getTopmostBottomTabRoute from './getTopmostBottomTabRoute'; import getTopmostCentralPaneRoute from './getTopmostCentralPaneRoute'; -import getTopmostReportId from './getTopmostReportId'; import linkingConfig from './linkingConfig'; import getAdaptedStateFromPath from './linkingConfig/getAdaptedStateFromPath'; import getMatchingBottomTabRouteForState from './linkingConfig/getMatchingBottomTabRouteForState'; @@ -32,6 +30,18 @@ type ActionPayload = { params?: ActionPayloadParams; }; +// eslint-disable-next-line @typescript-eslint/ban-types +const shallowCompare = (obj1?: object, obj2?: object) => { + if (!obj1 && !obj2) { + return true; + } + if (obj1 && obj2) { + // @ts-expect-error we know that obj1 and obj2 are params of a route. + return Object.keys(obj1).length === Object.keys(obj2).length && Object.keys(obj1).every((key) => obj1[key] === obj2[key]); + } + return false; +}; + /** * Motivation for this function is described in NAVIGATION.md * @@ -153,25 +163,15 @@ export default function linkTo(navigation: NavigationContainerRef Date: Wed, 10 Apr 2024 18:28:54 +0200 Subject: [PATCH 10/26] remove waitForNavigation and OnyxTabNavigator from SearchPageBottomTab --- src/pages/Search/SearchPageBottomTab.tsx | 54 +++++++++--------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index a1400f740abd..68c6598088cb 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -34,54 +34,38 @@ function SearchPageBottomTab() { { title: 'All', icon: Expensicons.ExpensifyLogoNew, - action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('all')))), + action: singleExecution(() => Navigation.navigate(ROUTES.SEARCH.getRoute('all'))), }, { title: 'Sent', icon: Expensicons.ExpensifyLogoNew, - action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('sent')))), + action: singleExecution(() => Navigation.navigate(ROUTES.SEARCH.getRoute('sent'))), }, { title: 'Drafts', icon: Expensicons.ExpensifyLogoNew, - action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.SEARCH.getRoute('drafts')))), + action: singleExecution(() => Navigation.navigate(ROUTES.SEARCH.getRoute('drafts'))), }, ]; return ( - {isSmallScreenWidth ? ( - Navigation.navigate(ROUTES.SEARCH.getRoute(tab))} - > - {() => } - {() => } - {() => } - - ) : ( - - {/* - Ideally we should use MenuList component for MenuItems with singleExecution/Navigation actions. - In this case where user can click on workspace avatar or menu items, we need to have a check for `isExecuting`. So, we are directly mapping menuItems. - */} - {searchMenuItems.map((item) => ( - - ))} - - )} + + {searchMenuItems.map((item) => ( + + ))} + ); } From 2d78c11a8c6fe55f4fe6d8e8cfe1015adc259bd7 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 18:29:34 +0200 Subject: [PATCH 11/26] remove waitForNavigation and OnyxTabNavigator from SearchPageBottomTab v2 --- src/pages/Search/SearchPageBottomTab.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index 68c6598088cb..32ba8beac1ef 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -1,20 +1,16 @@ -import React, {useState} from 'react'; +import React from 'react'; import {View} from 'react-native'; import MenuItem from '@components/MenuItem'; import ScreenWrapper from '@components/ScreenWrapper'; -import TabSelector from '@components/TabSelector/TabSelector'; import useActiveRoute from '@hooks/useActiveRoute'; import useSingleExecution from '@hooks/useSingleExecution'; import useThemeStyles from '@hooks/useThemeStyles'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; -import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator'; import * as Expensicons from '@src/components/Icon/Expensicons'; -import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type IconAsset from '@src/types/utils/IconAsset'; -import SearchResults from './SearchResults'; type SearchMenuItem = { title: string; @@ -25,8 +21,6 @@ type SearchMenuItem = { function SearchPageBottomTab() { const styles = useThemeStyles(); const {singleExecution} = useSingleExecution(); - const {isSmallScreenWidth} = useWindowDimensions(); - const waitForNavigate = useWaitForNavigation(); const activeRoute = useActiveRoute(); const currentQuery = activeRoute?.params?.query; From b57d45603adfc9c0fef8acebd0bd609ff0f1c906 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 18:36:12 +0200 Subject: [PATCH 12/26] add customBackHandler --- src/pages/Search/SearchPage.tsx | 5 ++- .../useCustomBackHandler/index.android.ts | 32 +++++++++++++++++++ .../Search/useCustomBackHandler/index.ts | 3 ++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/pages/Search/useCustomBackHandler/index.android.ts create mode 100644 src/pages/Search/useCustomBackHandler/index.ts diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 488ce1dbb28a..135ab66276a2 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -4,10 +4,13 @@ import ScreenWrapper from '@components/ScreenWrapper'; import type {CentralPaneNavigatorParamList} from '@libs/Navigation/types'; import type SCREENS from '@src/SCREENS'; import SearchResults from './SearchResults'; +import useCustomBackHandler from './useCustomBackHandler'; -type SearchPageProps = StackScreenProps; +type SearchPageProps = StackScreenProps; function SearchPage({route}: SearchPageProps) { + useCustomBackHandler(); + return ( diff --git a/src/pages/Search/useCustomBackHandler/index.android.ts b/src/pages/Search/useCustomBackHandler/index.android.ts new file mode 100644 index 000000000000..cc9d5d3ca198 --- /dev/null +++ b/src/pages/Search/useCustomBackHandler/index.android.ts @@ -0,0 +1,32 @@ +import {StackActions, useFocusEffect} from '@react-navigation/native'; +import {useCallback} from 'react'; +import {BackHandler} from 'react-native'; +import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; +import navigationRef from '@libs/Navigation/navigationRef'; +import type {RootStackParamList, State} from '@libs/Navigation/types'; +import NAVIGATORS from '@src/NAVIGATORS'; +import SCREENS from '@src/SCREENS'; + +function useCustomBackHandler() { + useFocusEffect( + useCallback(() => { + const onBackPress = () => { + const rootState = navigationRef.getRootState(); + + const bottomTabRoute = rootState.routes.find((route) => route.name === NAVIGATORS.BOTTOM_TAB_NAVIGATOR); + const centralPaneRouteAfterPop = getTopmostCentralPaneRoute({routes: [rootState.routes.at(-2)]} as State); + + if (bottomTabRoute && bottomTabRoute.state && (!centralPaneRouteAfterPop || centralPaneRouteAfterPop.name !== SCREENS.SEARCH.CENTRAL_PANE)) { + navigationRef.dispatch({...StackActions.pop(), target: bottomTabRoute.state.key}); + } + return false; + }; + + const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress); + + return () => subscription.remove(); + }, []), + ); +} + +export default useCustomBackHandler; diff --git a/src/pages/Search/useCustomBackHandler/index.ts b/src/pages/Search/useCustomBackHandler/index.ts new file mode 100644 index 000000000000..be753de818a6 --- /dev/null +++ b/src/pages/Search/useCustomBackHandler/index.ts @@ -0,0 +1,3 @@ +function useCustomBackHandler() {} + +export default useCustomBackHandler; From 2fcae18f57c3dfb6f9e566bd29eac514d30e543b Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 10 Apr 2024 18:38:41 +0200 Subject: [PATCH 13/26] remove unused imports --- src/pages/Search/SearchPageBottomTab.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx index 32ba8beac1ef..96b6aaf191fd 100644 --- a/src/pages/Search/SearchPageBottomTab.tsx +++ b/src/pages/Search/SearchPageBottomTab.tsx @@ -5,8 +5,6 @@ import ScreenWrapper from '@components/ScreenWrapper'; import useActiveRoute from '@hooks/useActiveRoute'; import useSingleExecution from '@hooks/useSingleExecution'; import useThemeStyles from '@hooks/useThemeStyles'; -import useWaitForNavigation from '@hooks/useWaitForNavigation'; -import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; import * as Expensicons from '@src/components/Icon/Expensicons'; import ROUTES from '@src/ROUTES'; From 1de5ce37cdb66f679ac98f6a49b2f1d0256ca85c Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 16 Apr 2024 13:05:57 +0200 Subject: [PATCH 14/26] Add a tooltip for the search icon in the bottom tab --- .../createCustomBottomTabNavigator/BottomTabBar.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index f6e058242b7f..41d6f25f3353 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -101,6 +101,8 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps )} + + { Navigation.navigate(ROUTES.SEARCH.getRoute('all')); @@ -120,7 +122,6 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps - From f84911bf10eb9ab604ca11e1e87ab7c85c4d9531 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 16 Apr 2024 15:38:00 +0200 Subject: [PATCH 15/26] Add SEARCH_QUERIES consts, hide new features --- src/CONST.ts | 6 ++++++ src/components/TestToolMenu.tsx | 11 +++++++++++ .../createCustomBottomTabNavigator/BottomTabBar.tsx | 9 +++++---- src/pages/Search/SearchPage.tsx | 2 +- src/pages/Search/SearchPageBottomTab.tsx | 9 +++++---- src/pages/Search/SearchResults.tsx | 9 ++++++--- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d23a7f695ddc..10c1b5679a8f 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4345,6 +4345,12 @@ const CONST = { MAX_TAX_RATE_INTEGER_PLACES: 4, MAX_TAX_RATE_DECIMAL_PLACES: 4, + + SEARCH_QUERIES: { + ALL: 'all', + SENT: 'sent', + DRAFTS: 'drafts' + } } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/components/TestToolMenu.tsx b/src/components/TestToolMenu.tsx index 5efa9592034f..3299b7e4f0c4 100644 --- a/src/components/TestToolMenu.tsx +++ b/src/components/TestToolMenu.tsx @@ -10,6 +10,7 @@ import * as Network from '@userActions/Network'; import * as Session from '@userActions/Session'; import * as User from '@userActions/User'; import CONFIG from '@src/CONFIG'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Network as NetworkOnyx, User as UserOnyx} from '@src/types/onyx'; @@ -103,6 +104,16 @@ function TestToolMenu({user = USER_DEFAULT, network}: TestToolMenuProps) { }} /> + {/* Navigate to the new Search Page. This button is temporary and should be removed after passing QA tests. */} + +