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

Add useActiveWorkspaceFromNavigationState #40016

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
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 @@ -76,7 +76,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 @@ -829,9 +828,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 @@ -414,49 +405,48 @@ function findCurrentXeroOrganization(tenants: Tenant[] | undefined, organization
}

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
Loading