Skip to content

Commit

Permalink
Merge pull request #40016 from software-mansion-labs/fix/refresh-page…
Browse files Browse the repository at this point in the history
…-with-workspace

Add useActiveWorkspaceFromNavigationState
  • Loading branch information
roryabraham committed May 14, 2024
2 parents fc835c4 + e68b2fb commit ce4939c
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 51 deletions.
27 changes: 27 additions & 0 deletions src/hooks/useActiveWorkspaceFromNavigationState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {useNavigationState} from '@react-navigation/native';
import Log from '@libs/Log';
import type {BottomTabNavigatorParamList} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';

/**
* Get the currently selected policy ID stored in the navigation state. This hook should only be called only from screens in BottomTab.
* Differences between this hook and useActiveWorkspace:
* - useActiveWorkspaceFromNavigationState reads the active workspace id directly from the navigation state, it's a bit slower than useActiveWorkspace and it can be called only from BottomTabScreens.
* It allows to read a value of policyID immediately after the update.
* - useActiveWorkspace allows to read the current policyID anywhere, it's faster because it doesn't require searching in the navigation state.
*/
function useActiveWorkspaceFromNavigationState() {
// The last policyID value is always stored in the last route in BottomTabNavigator.
const activeWorkpsaceID = useNavigationState<BottomTabNavigatorParamList, string | undefined>((state) => {
// SCREENS.HOME is a screen located in the BottomTabNavigator, if it's not in state.routeNames it means that this hook was called from a screen in another navigator.
if (!state.routeNames.includes(SCREENS.HOME)) {
Log.warn('useActiveWorkspaceFromNavigationState should be called only from BottomTab screens');
}

return state.routes.at(-1)?.params?.policyID;
});

return activeWorkpsaceID;
}

export default useActiveWorkspaceFromNavigationState;
7 changes: 3 additions & 4 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ type BackToParams = {
};

type SettingsNavigatorParamList = {
[SCREENS.SETTINGS.ROOT]: undefined;
[SCREENS.SETTINGS.SHARE_CODE]: undefined;
[SCREENS.SETTINGS.PROFILE.ROOT]: undefined;
[SCREENS.SETTINGS.PROFILE.PRONOUNS]: undefined;
Expand Down Expand Up @@ -830,9 +829,9 @@ type WelcomeVideoModalNavigatorParamList = {
};

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

type SharedScreensParamList = {
Expand Down
76 changes: 33 additions & 43 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import type {PolicyFeatureName, Rate, Tenant} from '@src/types/onyx/Policy';
import type PolicyEmployee from '@src/types/onyx/PolicyEmployee';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import getPolicyIDFromState from './Navigation/getPolicyIDFromState';
import Navigation, {navigationRef} from './Navigation/Navigation';
import type {RootStackParamList, State} from './Navigation/types';
import Navigation from './Navigation/Navigation';
import * as NetworkStore from './Network/NetworkStore';
import {getAccountIDsByLogins, getLoginsByAccountIDs, getPersonalDetailByEmail} from './PersonalDetailsUtils';

Expand Down Expand Up @@ -367,13 +365,6 @@ function getPersonalPolicy() {
return Object.values(allPolicies ?? {}).find((policy) => policy?.type === CONST.POLICY.TYPE.PERSONAL);
}

/**
* Get the currently selected policy ID stored in the navigation state.
*/
function getPolicyIDFromNavigationState() {
return getPolicyIDFromState(navigationRef.getRootState() as State<RootStackParamList>);
}

function getAdminEmployees(policy: OnyxEntry<Policy>): PolicyEmployee[] {
return Object.values(policy?.employeeList ?? {}).filter((employee) => employee.role === CONST.POLICY.ROLE.ADMIN);
}
Expand Down Expand Up @@ -418,49 +409,48 @@ function getCurrentXeroOrganizationName(policy: Policy | undefined): string | un
}

export {
canEditTaxRate,
extractPolicyIDFromPath,
getActivePolicies,
getAdminEmployees,
getCleanedTagName,
getCountOfEnabledTagsOfList,
getIneligibleInvitees,
getMemberAccountIDsForWorkspace,
getNumericValue,
isMultiLevelTags,
getPathWithoutPolicyID,
getPersonalPolicy,
getPolicy,
getPolicyBrickRoadIndicatorStatus,
getPolicyEmployeeListByIdWithoutCurrentUser,
getSortedTagKeys,
getSubmitToAccountID,
getTagList,
getTagListName,
getTagLists,
getTaxByID,
getUnitRateValue,
goBackFromInvalidPolicy,
hasAccountingConnections,
hasCustomUnitsError,
hasEmployeeListError,
hasPolicyCategoriesError,
hasPolicyError,
hasPolicyErrorFields,
hasCustomUnitsError,
getNumericValue,
getUnitRateValue,
getPolicyBrickRoadIndicatorStatus,
shouldShowPolicy,
hasTaxRateError,
isExpensifyTeam,
isInstantSubmitEnabled,
isFreeGroupPolicy,
isPolicyAdmin,
isTaxTrackingEnabled,
isSubmitAndClose,
getMemberAccountIDsForWorkspace,
getIneligibleInvitees,
getTagLists,
getTagListName,
getSortedTagKeys,
canEditTaxRate,
getTagList,
getCleanedTagName,
getCountOfEnabledTagsOfList,
isMultiLevelTags,
isInstantSubmitEnabled,
isPaidGroupPolicy,
isPendingDeletePolicy,
isPolicyAdmin,
isPolicyEmployee,
isPolicyOwner,
isPaidGroupPolicy,
extractPolicyIDFromPath,
getPathWithoutPolicyID,
getPolicyEmployeeListByIdWithoutCurrentUser,
goBackFromInvalidPolicy,
getPersonalPolicy,
isPolicyFeatureEnabled,
hasTaxRateError,
getTaxByID,
hasPolicyCategoriesError,
getPolicyIDFromNavigationState,
getSubmitToAccountID,
getAdminEmployees,
getPolicy,
isPolicyOwner,
isSubmitAndClose,
isTaxTrackingEnabled,
shouldShowPolicy,
getActiveAdminWorkspaces,
canSendInvoice,
getXeroTenants,
Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/sidebar/SidebarLinksData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import type {EdgeInsets} from 'react-native-safe-area-context';
import type {ValueOf} from 'type-fest';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useActiveWorkspaceFromNavigationState from '@hooks/useActiveWorkspaceFromNavigationState';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import type {PolicySelector} from '@hooks/useReportIDs';
Expand Down Expand Up @@ -41,7 +41,7 @@ function SidebarLinksData({insets, isLoadingApp = true, onLinkClick, priorityMod
const {accountID} = useCurrentUserPersonalDetails();
const isFocused = useIsFocused();
const styles = useThemeStyles();
const {activeWorkspaceID} = useActiveWorkspace();
const activeWorkspaceID = useActiveWorkspaceFromNavigationState();
const {translate} = useLocalize();

const policyMemberAccountIDs = getPolicyEmployeeListByIdWithoutCurrentUser(policies, activeWorkspaceID, accountID);
Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, {useEffect} from 'react';
import {View} from 'react-native';
import ScreenWrapper from '@components/ScreenWrapper';
import useActiveWorkspaceFromNavigationState from '@hooks/useActiveWorkspaceFromNavigationState';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import TopBar from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar';
import Performance from '@libs/Performance';
import {getPolicyIDFromNavigationState} from '@libs/PolicyUtils';
import SidebarLinksData from '@pages/home/sidebar/SidebarLinksData';
import Timing from '@userActions/Timing';
import CONST from '@src/CONST';
Expand All @@ -21,7 +21,7 @@ const startTimer = () => {

function BaseSidebarScreen() {
const styles = useThemeStyles();
const activeWorkspaceID = getPolicyIDFromNavigationState();
const activeWorkspaceID = useActiveWorkspaceFromNavigationState();
const {translate} = useLocalize();

useEffect(() => {
Expand Down
1 change: 1 addition & 0 deletions tests/perf-test/SidebarLinks.perf-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatch

jest.mock('@libs/Permissions');
jest.mock('@hooks/usePermissions.ts');
jest.mock('@src/hooks/useActiveWorkspaceFromNavigationState');
jest.mock('@libs/Navigation/Navigation');
jest.mock('@components/Icon/Expensicons');

Expand Down
1 change: 1 addition & 0 deletions tests/unit/SidebarOrderTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatch
jest.mock('@libs/Permissions');
jest.mock('@hooks/usePermissions.ts');
jest.mock('@components/Icon/Expensicons');
jest.mock('@src/hooks/useActiveWorkspaceFromNavigationState');

const ONYXKEYS = {
PERSONAL_DETAILS_LIST: 'personalDetailsList',
Expand Down
1 change: 1 addition & 0 deletions tests/unit/SidebarTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatch
// Be sure to include the mocked Permissions and Expensicons libraries as well as the usePermissions hook or else the beta tests won't work
jest.mock('@src/libs/Permissions');
jest.mock('@src/hooks/usePermissions.ts');
jest.mock('@src/hooks/useActiveWorkspaceFromNavigationState');
jest.mock('@src/components/Icon/Expensicons');

describe('Sidebar', () => {
Expand Down

0 comments on commit ce4939c

Please sign in to comment.