Skip to content

Commit

Permalink
Merge pull request Expensify#49226 from dominictb/fix/46646
Browse files Browse the repository at this point in the history
fix: app goes to workspace initial page when back from not found page
  • Loading branch information
lakchote authored Nov 7, 2024
2 parents 633c99c + 63029f1 commit f05be95
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
import type {ParamListBase, PartialState, RouterConfigOptions, StackNavigationState} from '@react-navigation/native';
import {StackRouter} from '@react-navigation/native';
import Onyx from 'react-native-onyx';
import getIsNarrowLayout from '@libs/getIsNarrowLayout';
import * as PolicyUtils from '@libs/PolicyUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import type {FullScreenNavigatorRouterOptions} from './types';

type StackState = StackNavigationState<ParamListBase> | PartialState<StackNavigationState<ParamListBase>>;

const isAtLeastOneInState = (state: StackState, screenName: string): boolean => state.routes.some((route) => route.name === screenName);

let isLoadingReportData = true;
Onyx.connect({
key: ONYXKEYS.IS_LOADING_REPORT_DATA,
initWithStoredValues: false,
callback: (value) => (isLoadingReportData = value ?? false),
});

function adaptStateIfNecessary(state: StackState) {
const isNarrowLayout = getIsNarrowLayout();
const workspaceCentralPane = state.routes.at(-1);
const policyID =
workspaceCentralPane?.params && 'policyID' in workspaceCentralPane.params && typeof workspaceCentralPane.params.policyID === 'string'
? workspaceCentralPane.params.policyID
: undefined;
const policy = PolicyUtils.getPolicy(policyID ?? '');
const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy);

// There should always be WORKSPACE.INITIAL screen in the state to make sure go back works properly if we deeplinkg to a subpage of settings.
// The only exception is when the workspace is invalid or inaccessible.
if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) {
if (isNarrowLayout && !isLoadingReportData && !isPolicyAccessible) {
return;
}
// @ts-expect-error Updating read only property
// noinspection JSConstantReassignment
state.stale = true; // eslint-disable-line
Expand Down
16 changes: 16 additions & 0 deletions src/libs/Navigation/Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {HybridAppRoute, Route} from '@src/ROUTES';
import ROUTES, {HYBRID_APP_ROUTES} from '@src/ROUTES';
import {PROTECTED_SCREENS} from '@src/SCREENS';
import type {Screen} from '@src/SCREENS';
import type {Report} from '@src/types/onyx';
import originalCloseRHPFlow from './closeRHPFlow';
import originalDismissModal from './dismissModal';
Expand Down Expand Up @@ -418,6 +419,20 @@ function getTopMostCentralPaneRouteFromRootState() {
return getTopmostCentralPaneRoute(navigationRef.getRootState() as State<RootStackParamList>);
}

function removeScreenFromNavigationState(screen: Screen) {
isNavigationReady().then(() => {
navigationRef.dispatch((state) => {
const routes = state.routes?.filter((item) => item.name !== screen);

return CommonActions.reset({
...state,
routes,
index: routes.length < state.routes.length ? state.index - 1 : state.index,
});
});
});
}

export default {
setShouldPopAllStateOnUP,
navigate,
Expand All @@ -442,6 +457,7 @@ export default {
closeRHPFlow,
setNavigationActionToMicrotaskQueue,
getTopMostCentralPaneRouteFromRootState,
removeScreenFromNavigationState,
};

export {navigationRef};
5 changes: 5 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,10 @@ function getActivePolicy(): OnyxEntry<Policy> {
return getPolicy(activePolicyId);
}

function isPolicyAccessible(policy: OnyxEntry<Policy>): boolean {
return !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && !!policy?.id;
}

export {
canEditTaxRate,
extractPolicyIDFromPath,
Expand Down Expand Up @@ -1181,6 +1185,7 @@ export {
getNetSuiteImportCustomFieldLabel,
getAllPoliciesLength,
getActivePolicy,
isPolicyAccessible,
};

export type {MemberEmailsToAccountIDs};
11 changes: 10 additions & 1 deletion src/pages/workspace/AccessOrNotFoundWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {IOUType} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';
import type {PolicyFeatureName} from '@src/types/onyx/Policy';
import callOrReturn from '@src/types/utils/callOrReturn';
Expand Down Expand Up @@ -152,7 +153,7 @@ function AccessOrNotFoundWrapper({
return acc && accessFunction(policy, login, report, allPolicies ?? null, iouType);
}, true);

const isPolicyNotAccessible = isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id;
const isPolicyNotAccessible = !PolicyUtils.isPolicyAccessible(policy);
const shouldShowNotFoundPage = (!isMoneyRequest && !isFromGlobalCreate && isPolicyNotAccessible) || !isPageAccessible || !isPolicyFeatureEnabled || shouldBeBlocked;

// We only update the feature state if it isn't pending.
Expand All @@ -165,6 +166,14 @@ function AccessOrNotFoundWrapper({
setIsPolicyFeatureEnabled(isFeatureEnabled);
}, [pendingField, isOffline, isFeatureEnabled]);

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (isLoadingReportData || !isPolicyNotAccessible) {
return;
}
Navigation.removeScreenFromNavigationState(SCREENS.WORKSPACE.INITIAL);
}, [isLoadingReportData, isPolicyNotAccessible]);

if (shouldShowFullScreenLoadingIndicator) {
return <FullscreenLoadingIndicator />;
}
Expand Down

0 comments on commit f05be95

Please sign in to comment.