Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Search v1] Implement Search navigation logic #40280

Merged
merged 30 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c96e516
migrate search page to find page v1
adamgrzybowski Apr 5, 2024
1e5150b
add new search tab
adamgrzybowski Apr 5, 2024
eef26cc
Add search page template components
WojtekBoman Apr 8, 2024
3c74507
Add new search pages
WojtekBoman Apr 9, 2024
a707c28
remove native.tsx for createCustomStackNavigator
adamgrzybowski Apr 10, 2024
3afd0b9
add check for search page in getAdaptedStateFromPath
adamgrzybowski Apr 10, 2024
2206c1d
Handle passing params to useActiveRoute
WojtekBoman Apr 10, 2024
e7de7ea
Merge branch 'new-search-tab' into new-search-tab-poc
WojtekBoman Apr 10, 2024
b9d88d9
Merge pull request #85 from software-mansion-labs/new-search-tab-poc
WojtekBoman Apr 10, 2024
a1b228a
Adjust getAdaptedStateFromPath to new search routes
WojtekBoman Apr 10, 2024
a72d221
fix linnkTo
adamgrzybowski Apr 10, 2024
633d881
remove waitForNavigation and OnyxTabNavigator from SearchPageBottomTab
adamgrzybowski Apr 10, 2024
2d78c11
remove waitForNavigation and OnyxTabNavigator from SearchPageBottomTa…
adamgrzybowski Apr 10, 2024
b57d456
add customBackHandler
adamgrzybowski Apr 10, 2024
2fcae18
remove unused imports
adamgrzybowski Apr 10, 2024
18ed94f
Merge branch 'main' into new-search-tab
WojtekBoman Apr 16, 2024
1de5ce3
Add a tooltip for the search icon in the bottom tab
WojtekBoman Apr 16, 2024
f84911b
Add SEARCH_QUERIES consts, hide new features
WojtekBoman Apr 16, 2024
8ea25e3
Remove SEARCH_QUERIES const
WojtekBoman Apr 16, 2024
5ea4a9f
Remove test page
WojtekBoman Apr 16, 2024
2e38d66
add comment for useCustomBackHandler
adamgrzybowski Apr 16, 2024
f724761
Exclude shallowCompare function
WojtekBoman Apr 16, 2024
f28c388
Merge branch 'main' into search-v1/nav-logic
WojtekBoman Apr 17, 2024
1b33065
Remove redundant const
WojtekBoman Apr 17, 2024
39a308a
Remove test code from TabSelector
WojtekBoman Apr 17, 2024
0c538bb
Refactor createCustomStackNavigator
WojtekBoman Apr 17, 2024
3cb9dbe
Refactor search pages
WojtekBoman Apr 17, 2024
faf9a69
Remove unused code
WojtekBoman Apr 17, 2024
87a4076
Remove unused code
WojtekBoman Apr 17, 2024
3b7a83d
Handle displaying FAB on the new search page
WojtekBoman Apr 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3301,6 +3301,13 @@ const CONST = {
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: {
Expand Down
5 changes: 5 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ const ROUTES = {

ALL_SETTINGS: 'all-settings',

SEARCH: {
route: '/search/:query',
getRoute: (query: string) => `search/${query}` 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: {
Expand Down
4 changes: 4 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const SCREENS = {
UNLINK_LOGIN: 'UnlinkLogin',
SETTINGS_CENTRAL_PANE: 'SettingsCentralPane',
WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane',
SEARCH: {
CENTRAL_PANE: 'Search_Central_Pane',
BOTTOM_TAB: 'Search_Bottom_Tab',
},
SETTINGS: {
ROOT: 'Settings_Root',
SHARE_CODE: 'Settings_Share_Code',
Expand Down
11 changes: 11 additions & 0 deletions src/components/TestToolMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -103,6 +104,16 @@ function TestToolMenu({user = USER_DEFAULT, network}: TestToolMenuProps) {
}}
/>
</TestToolRow>
{/* Navigate to the new Search Page. This button is temporary and should be removed after passing QA tests. */}
<TestToolRow title="New Search Page">
<Button
small
text="Navigate"
onPress={() => {
Navigation.navigate(ROUTES.SEARCH.getRoute(CONST.TAB_SEARCH.ALL));
}}
/>
</TestToolRow>
</>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useActiveRoute.ts
Original file line number Diff line number Diff line change
@@ -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<keyof CentralPaneNavigatorParamList> | undefined {
return useContext(ActiveRouteContext);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import type {CentralPaneNavigatorParamList, NavigationPartialRoute} from '@libs/Navigation/types';

const ActiveRouteContext = React.createContext('');
const ActiveRouteContext = React.createContext<NavigationPartialRoute<keyof CentralPaneNavigatorParamList> | undefined>(undefined);

export default ActiveRouteContext;
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -21,12 +22,16 @@ function BottomTabNavigator() {
const activeRoute = useNavigationState(getTopmostCentralPaneRoute);

return (
<ActiveRouteContext.Provider value={activeRoute?.name ?? ''}>
<ActiveRouteContext.Provider value={activeRoute}>
<Tab.Navigator screenOptions={screenOptions}>
<Tab.Screen
name={SCREENS.HOME}
component={SidebarScreen}
/>
<Tab.Screen
name={SCREENS.SEARCH.BOTTOM_TAB}
component={SearchPageBottomTab}
/>
<Tab.Screen
name={SCREENS.SETTINGS.ROOT}
getComponent={loadInitialSettingsPage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import type {CentralPaneNavigatorParamList} from '@navigation/types';
import SearchPage from '@pages/Search/SearchPage';
import SCREENS from '@src/SCREENS';

const Stack = createStackNavigator<CentralPaneNavigatorParamList>();
Expand Down Expand Up @@ -41,6 +42,12 @@ function BaseCentralPaneNavigator() {
initialParams={{openOnAdminRoom: openOnAdminRoom === 'true' || undefined}}
component={ReportScreenWrapper}
/>
<Stack.Screen
name={SCREENS.SEARCH.CENTRAL_PANE}
// We do it this way to avoid adding the url params to url
component={SearchPage}
/>

{Object.entries(settingsScreens).map(([screenName, componentGetter]) => (
<Stack.Screen
key={screenName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@libs/actions/Session';
import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute';
import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute';
import Navigation from '@libs/Navigation/Navigation';
import type {RootStackParamList, State} from '@libs/Navigation/types';
import {getChatTabBrickRoad} from '@libs/WorkspacesSettingsUtils';
Expand Down Expand Up @@ -64,6 +65,12 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps

// Parent navigator of the bottom tab bar is the root navigator.
const currentTabName = useNavigationState<RootStackParamList, string | undefined>((state) => {
const topmostCentralPaneRoute = getTopmostCentralPaneRoute(state);

if (topmostCentralPaneRoute && topmostCentralPaneRoute.name === SCREENS.SEARCH.CENTRAL_PANE) {
return SCREENS.SEARCH.CENTRAL_PANE;
}

const topmostBottomTabRoute = getTopmostBottomTabRoute(state);
return topmostBottomTabRoute?.name ?? SCREENS.HOME;
});
Expand Down Expand Up @@ -95,7 +102,6 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps
</View>
</PressableWithFeedback>
</Tooltip>

<BottomTabBarFloatingActionButton />
<BottomTabAvatar isSelected={currentTabName === SCREENS.SETTINGS.ROOT} />
</View>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ 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 useThemeStyles from '@hooks/useThemeStyles';
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<ParamListBase>['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++;
Expand All @@ -32,6 +37,7 @@ function reduceReportRoutes(routes: Routes): Routes {

function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
const {isSmallScreenWidth} = useWindowDimensions();
const styles = useThemeStyles();

const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder<
StackNavigationState<ParamListBase>,
Expand All @@ -52,15 +58,35 @@ 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<RootStackParamList>)?.name === SCREENS.SEARCH.CENTRAL_PANE;

const firstRoute = routes[0];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add comment here

On narrow layout, if we are on /search route we want to hide all central pane routes and show only the bottom tab navigator.

// On narrow layout, if we are on /search route we want to hide all central pane routes and show only the bottom tab navigator.
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 (
<NavigationContent>
Expand All @@ -71,6 +97,7 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) {
descriptors={descriptors}
navigation={navigation}
/>
{searchRoute && <View style={styles.dNone}>{descriptors[searchRoute.key].render()}</View>}
</NavigationContent>
);
}
Expand Down
13 changes: 1 addition & 12 deletions src/libs/Navigation/AppNavigator/getPartialStateDiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,9 @@ import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRo
import getTopmostFullScreenRoute from '@libs/Navigation/getTopmostFullScreenRoute';
import type {Metainfo} from '@libs/Navigation/linkingConfig/getAdaptedStateFromPath';
import type {NavigationPartialRoute, RootStackParamList, State} from '@libs/Navigation/types';
import shallowCompare from '@libs/ObjectUtils';
import NAVIGATORS from '@src/NAVIGATORS';

// 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;
};

type GetPartialStateDiffReturnType = {
[NAVIGATORS.BOTTOM_TAB_NAVIGATOR]?: NavigationPartialRoute;
[NAVIGATORS.CENTRAL_PANE_NAVIGATOR]?: NavigationPartialRoute;
Expand Down
11 changes: 5 additions & 6 deletions src/libs/Navigation/linkTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {getActionFromState} from '@react-navigation/core';
import type {NavigationAction, NavigationContainerRef, NavigationState, PartialState} from '@react-navigation/native';
import type {Writable} from 'type-fest';
import getIsNarrowLayout from '@libs/getIsNarrowLayout';
import shallowCompare from '@libs/ObjectUtils';
import {extractPolicyIDFromPath, getPathWithoutPolicyID} from '@libs/PolicyUtils';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
Expand All @@ -13,7 +14,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';
Expand Down Expand Up @@ -152,16 +152,15 @@ export default function linkTo(navigation: NavigationContainerRef<RootStackParam
const topRouteName = rootState?.routes?.at(-1)?.name;
const isTargetNavigatorOnTop = topRouteName === action.payload.name;

const isTargetScreenDifferentThanCurrent = Boolean(topmostCentralPaneRoute && topmostCentralPaneRoute.name !== action.payload.params?.screen);
const areParamsDifferent = !shallowCompare(topmostCentralPaneRoute?.params, action.payload.params?.params);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also caused #40743

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix for that has been already merged. Could you check if it still occurs in dev environment?


Comment on lines +155 to +157
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific case this is fixing? This is causing #41198

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has been introduced to handle changing filters on the new SearchPage, on this page we can navigate to the same page with a different value of the query param, so that's why we added it. To me, we should create a custom method to compare params. Report ids should be compared as before but in other cases we can use shallowCompare.
WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Thanks for the context!

// In case if type is 'FORCED_UP' we replace current screen with the provided. This means the current screen no longer exists in the stack
if (type === CONST.NAVIGATION.TYPE.FORCED_UP) {
action.type = CONST.NAVIGATION.ACTION_TYPE.REPLACE;

// If this action is navigating to the report screen and the top most navigator is different from the one we want to navigate - PUSH the new screen to the top of the stack
} else if (
action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR &&
topmostCentralPaneRoute &&
(topmostCentralPaneRoute.name !== action.payload.params?.screen || getTopmostReportId(rootState) !== getTopmostReportId(stateFromPath))
) {
} else if (action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && (isTargetScreenDifferentThanCurrent || areParamsDifferent)) {
// We need to push a tab if the tab doesn't match the central pane route that we are going to push.
const topmostBottomTabRoute = getTopmostBottomTabRoute(rootState);
const matchingBottomTabRoute = getMatchingBottomTabRouteForState(stateFromPath, policyID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import SCREENS from '@src/SCREENS';

const TAB_TO_CENTRAL_PANE_MAPPING: Record<BottomTabName, CentralPaneName[]> = {
[SCREENS.HOME]: [SCREENS.REPORT],
[SCREENS.SEARCH.BOTTOM_TAB]: [SCREENS.SEARCH.CENTRAL_PANE],
[SCREENS.SETTINGS.ROOT]: [
SCREENS.SETTINGS.PROFILE.ROOT,
SCREENS.SETTINGS.PREFERENCES.ROOT,
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
exact: true,
},
[SCREENS.SETTINGS.WORKSPACES]: ROUTES.SETTINGS_WORKSPACES,
[SCREENS.SEARCH.CENTRAL_PANE]: ROUTES.SEARCH.route,
[SCREENS.SETTINGS.SAVE_THE_WORLD]: ROUTES.SETTINGS_SAVE_THE_WORLD,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,9 @@ function getAdaptedState(state: PartialState<NavigationState<RootStackParamList>
// 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,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type CentralPaneNavigatorParamList = {
[SCREENS.SETTINGS.ABOUT]: undefined;
[SCREENS.SETTINGS.TROUBLESHOOT]: undefined;
[SCREENS.SETTINGS.WORKSPACES]: undefined;
[SCREENS.SEARCH.CENTRAL_PANE]: {
query: string;
};
[SCREENS.SETTINGS.SAVE_THE_WORLD]: undefined;
};

Expand Down Expand Up @@ -724,6 +727,7 @@ type WelcomeVideoModalNavigatorParamList = {

type BottomTabNavigatorParamList = {
[SCREENS.HOME]: undefined;
[SCREENS.SEARCH.BOTTOM_TAB]: undefined;
[SCREENS.SETTINGS.ROOT]: undefined;
};

Expand Down
Loading
Loading