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

Improve goBack function #26498

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/components/InvertedFlatList/BaseInvertedFlatList.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {FlatList as NativeFlatlist, View} from 'react-native';
import _ from 'underscore';
import FlatList from '@components/FlatList';
import * as CollectionUtils from '@libs/CollectionUtils';
import variables from '@styles/variables';

const AUTOSCROLL_TO_TOP_THRESHOLD = 128;
Copy link
Contributor

Choose a reason for hiding this comment

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

This PR forgot to cover an extra case. More details here #30726


const propTypes = {
/** Same as FlatList can be any array of anything */
Expand Down Expand Up @@ -136,7 +137,7 @@ function BaseInvertedFlatList(props) {
windowSize={15}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
autoscrollToTopThreshold: variables.listItemHeightNormal,
autoscrollToTopThreshold: AUTOSCROLL_TO_TOP_THRESHOLD,
}}
inverted
/>
Expand Down
43 changes: 41 additions & 2 deletions src/libs/Navigation/Navigation.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getActionFromState} from '@react-navigation/core';
import {findFocusedRoute, getActionFromState} from '@react-navigation/core';
import {CommonActions, getPathFromState, StackActions} from '@react-navigation/native';
import _ from 'lodash';
import lodashGet from 'lodash/get';
Expand Down Expand Up @@ -73,6 +73,31 @@ const getActiveRouteIndex = function (route, index) {
return index;
};

/**
* Gets distance from the path in root navigator. In other words how much screen you have to pop to get to the route with this path.
* The search is limited to 5 screens from the top for performance reasons.
* @param {String} path - Path that you are looking for.
* @return {Number} - Returns distance to path or -1 if the path is not found in root navigator.
*/
function getDistanceFromPathInRootNavigator(path) {
let currentState = navigationRef.getRootState();

for (let index = 0; index < 5; index++) {
if (!currentState.routes.length) {
break;
}

const pathFromState = getPathFromState(currentState, linkingConfig.config);
if (path === pathFromState.substring(1)) {
return index;
}

currentState = {...currentState, routes: currentState.routes.slice(0, -1), index: currentState.index - 1};
}

return -1;
}

/**
* Main navigation method for redirecting to a route.
* @param {String} route
Expand Down Expand Up @@ -114,7 +139,6 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f
}

const isFirstRouteInNavigator = !getActiveRouteIndex(navigationRef.current.getState());

if (isFirstRouteInNavigator) {
const rootState = navigationRef.getRootState();
const lastRoute = _.last(rootState.routes);
Expand All @@ -130,6 +154,21 @@ function goBack(fallbackRoute, shouldEnforceFallback = false, shouldPopToTop = f
return;
}

const isCentralPaneFocused = findFocusedRoute(navigationRef.current.getState()).name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR;
const distanceFromPathInRootNavigator = getDistanceFromPathInRootNavigator(fallbackRoute);

// Allow CentralPane to use UP with fallback route if the path is not found in root navigator.
if (isCentralPaneFocused && fallbackRoute && distanceFromPathInRootNavigator === -1) {
navigate(fallbackRoute, CONST.NAVIGATION.TYPE.FORCED_UP);
return;
}

// Add posibility to go back more than one screen in root navigator if that screen is on the stack.
if (isCentralPaneFocused && fallbackRoute && distanceFromPathInRootNavigator > 0) {
navigationRef.current.dispatch(StackActions.pop(distanceFromPathInRootNavigator));
return;
}

navigationRef.current.goBack();
}

Expand Down
6 changes: 2 additions & 4 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -2188,15 +2188,13 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
// STEP 7: Navigate the user depending on which page they are on and which resources were deleted
if (isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
Navigation.goBack(ROUTES.HOME);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(iouReport.reportID));
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(iouReport.reportID));
return;
}

if (shouldDeleteIOUReport) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
Navigation.goBack(ROUTES.HOME);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(iouReport.chatReportID));
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(iouReport.chatReportID));
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/actions/IOUTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2635,14 +2635,14 @@ describe('actions/IOU', () => {

// Then we expect to navigate to the iou report

expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(IOU_REPORT_ID));
expect(Navigation.goBack).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(IOU_REPORT_ID));
});

it('navigate the user correctly to the chat Report when appropriate', () => {
// When we delete the money request and we should delete the IOU report
IOU.deleteMoneyRequest(transaction.transactionID, createIOUAction, false);
// Then we expect to navigate to the chat report
expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(chatReport.reportID));
expect(Navigation.goBack).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(chatReport.reportID));
});
});

Expand Down
Loading