Skip to content
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
6 changes: 3 additions & 3 deletions src/components/BookTravelButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false}: B
const [sessionEmail] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email, canBeMissing: false});
const primaryContactMethod = primaryLogin ?? sessionEmail ?? '';
const {setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
const {isBlockedFromSpotnanaTravel, isTravelVerified} = usePermissions();
const {isBlockedFromSpotnanaTravel, isBetaEnabled} = usePermissions();
const [isPreventionModalVisible, setPreventionModalVisibility] = useState(false);
const [isVerificationModalVisible, setVerificationModalVisibility] = useState(false);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
Expand Down Expand Up @@ -135,7 +135,7 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false}: B
});
} else if (isPolicyProvisioned) {
navigateToAcceptTerms(CONST.TRAVEL.DEFAULT_DOMAIN);
} else if (!isTravelVerified) {
} else if (!isBetaEnabled(CONST.BETAS.IS_TRAVEL_VERIFIED)) {
setVerificationModalVisibility(true);
}
// Determine the domain to associate with the workspace during provisioning in Spotnana.
Expand Down Expand Up @@ -166,7 +166,7 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false}: B
setRootStatusBarEnabled,
isUserValidated,
groupPaidPolicies.length,
isTravelVerified,
isBetaEnabled,
]);

return (
Expand Down
12 changes: 6 additions & 6 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ function MoneyReportHeader({
),
};

const {canUseRetractNewDot, canUseTableReportView, canUseNewDotSplits} = usePermissions();
const {isBetaEnabled} = usePermissions();

const beginPDFExport = (reportID: string) => {
setIsPDFModalVisible(true);
Expand All @@ -639,11 +639,11 @@ function MoneyReportHeader({
reportNameValuePairs,
reportActions,
policies,
canUseRetractNewDot,
canUseTableReportView,
canUseNewDotSplits,
isBetaEnabled(CONST.BETAS.RETRACT_NEWDOT),
isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW),
isBetaEnabled(CONST.BETAS.NEW_DOT_SPLITS),
);
}, [moneyRequestReport, transactions, violations, policy, reportNameValuePairs, reportActions, policies, canUseRetractNewDot, canUseTableReportView, canUseNewDotSplits]);
}, [moneyRequestReport, transactions, violations, policy, reportNameValuePairs, reportActions, policies, isBetaEnabled]);

const secondaryActionsImplementation: Record<
ValueOf<typeof CONST.REPORT.SECONDARY_ACTIONS>,
Expand Down Expand Up @@ -818,7 +818,7 @@ function MoneyReportHeader({
setIsDeleteReportModalVisible(true);
}
},
shouldShow: canUseTableReportView,
shouldShow: isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW),
},
[CONST.REPORT.SECONDARY_ACTIONS.RETRACT]: {
text: translate('iou.undoSubmit'),
Expand Down
8 changes: 4 additions & 4 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
import useDebouncedState from '@hooks/useDebouncedState';
import useLocalize from '@hooks/useLocalize';
import {MouseProvider} from '@hooks/useMouseContext';
import usePermissions from '@hooks/usePermissions';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
import blurActiveElement from '@libs/Accessibility/blurActiveElement';
Expand All @@ -32,7 +33,6 @@ import Log from '@libs/Log';
import {validateAmount} from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import {getIOUConfirmationOptionsFromPayeePersonalDetail, hasEnabledOptions} from '@libs/OptionsListUtils';
import Permissions from '@libs/Permissions';
import {getDistanceRateCustomUnitRate, getTagLists, isTaxTrackingEnabled} from '@libs/PolicyUtils';
import {isSelectedManagerMcTest} from '@libs/ReportUtils';
import type {OptionData} from '@libs/ReportUtils';
Expand Down Expand Up @@ -231,7 +231,7 @@ function MoneyRequestConfirmationList({
const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${policyID}`, {canBeMissing: true});
const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true});
const [currencyList] = useOnyx(ONYXKEYS.CURRENCY_LIST, {canBeMissing: false});
const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: false});
const {isBetaEnabled} = usePermissions();

const isTestReceipt = useMemo(() => {
return transaction?.receipt?.isTestReceipt ?? false;
Expand All @@ -242,8 +242,8 @@ function MoneyRequestConfirmationList({
}, [transaction?.receipt?.isTestDriveReceipt]);

const isManagerMcTestReceipt = useMemo(() => {
return Permissions.canUseManagerMcTest(betas) && selectedParticipantsProp.some((participant) => isSelectedManagerMcTest(participant.login));
}, [betas, selectedParticipantsProp]);
return isBetaEnabled(CONST.BETAS.NEWDOT_MANAGER_MCTEST) && selectedParticipantsProp.some((participant) => isSelectedManagerMcTest(participant.login));
}, [isBetaEnabled, selectedParticipantsProp]);

const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip} = useProductTrainingContext(
isTestDriveReceipt ? CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_DRIVE_CONFIRMATION : CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_CONFIRMATION,
Expand Down
6 changes: 3 additions & 3 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
const isOnHold = isOnHoldTransactionUtils(transaction);
const isDuplicate = isDuplicateTransactionUtils(transaction?.transactionID);
const reportID = report?.reportID;
const {canUseNewDotSplits} = usePermissions();
const {isBetaEnabled} = usePermissions();

const isReportInRHP = route.name === SCREENS.SEARCH.REPORT_RHP;
const shouldDisplayTransactionNavigation = !!(reportID && isReportInRHP);
Expand Down Expand Up @@ -203,8 +203,8 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
if (!transaction || !reportActions) {
return [];
}
return getSecondaryTransactionThreadActions(parentReport, transaction, Object.values(reportActions), policy, canUseNewDotSplits);
}, [canUseNewDotSplits, parentReport, policy, transaction]);
return getSecondaryTransactionThreadActions(parentReport, transaction, Object.values(reportActions), policy, isBetaEnabled(CONST.BETAS.NEW_DOT_SPLITS));
}, [isBetaEnabled, parentReport, policy, transaction]);

const secondaryActionsImplementation: Record<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS>, DropdownOption<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS>>> = {
[CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.HOLD]: {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ReportActionItem/MoneyRequestAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function MoneyRequestAction({
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {canUseTableReportView} = usePermissions();
const {isBetaEnabled} = usePermissions();
const route = useRoute<PlatformStackRouteProp<TransactionDuplicateNavigatorParamList, typeof SCREENS.TRANSACTION_DUPLICATE.REVIEW>>();
const isReviewDuplicateTransactionPage = route.name === SCREENS.TRANSACTION_DUPLICATE.REVIEW;
const isSplitBillAction = isSplitBillActionReportActionsUtils(action);
Expand Down Expand Up @@ -166,7 +166,7 @@ function MoneyRequestAction({
}

// Condition extracted from MoneyRequestPreview
const renderCondition = !(lodashIsEmpty(iouReport) && !(isSplitBillAction || isTrackExpenseAction)) && canUseTableReportView && isReviewDuplicateTransactionPage;
const renderCondition = !(lodashIsEmpty(iouReport) && !(isSplitBillAction || isTrackExpenseAction)) && isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW) && isReviewDuplicateTransactionPage;
const isLayoutWidthInvalid = (layoutWidth: number) => {
return (shouldUseNarrowLayout && layoutWidth > variables.mobileResponsiveWidthBreakpoint) || (!shouldUseNarrowLayout && layoutWidth > variables.sideBarWidth);
};
Expand Down
6 changes: 3 additions & 3 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS

const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS;

const {canUseTableReportView} = usePermissions();
const {isBetaEnabled} = usePermissions();

useEffect(() => {
clearSelectedTransactions(hash);
Expand Down Expand Up @@ -433,7 +433,7 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS

const shouldHandleTransactionAsReport = isReportListItemType(item) || (isTransactionItem && isOpenedAsReport);

if (canUseTableReportView && shouldHandleTransactionAsReport) {
if (isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW) && shouldHandleTransactionAsReport) {
Navigation.navigate(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID, backTo}));
return;
}
Expand All @@ -446,7 +446,7 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS

Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, backTo}));
},
[canUseTableReportView, hash, selectionMode?.isEnabled, toggleTransaction],
[isBetaEnabled, hash, selectionMode?.isEnabled, toggleTransaction],
);

const onViewableItemsChanged = useCallback(
Expand Down
8 changes: 3 additions & 5 deletions src/components/SelectionList/InviteMemberListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {Str} from 'expensify-common';
import React, {useCallback} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import {FallbackAvatar} from '@components/Icon/Expensicons';
import MultipleAvatars from '@components/MultipleAvatars';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
Expand All @@ -12,14 +11,13 @@ import Text from '@components/Text';
import TextWithTooltip from '@components/TextWithTooltip';
import EducationalTooltip from '@components/Tooltip/EducationalTooltip';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {getIsUserSubmittedExpenseOrScannedReceipt} from '@libs/OptionsListUtils';
import Permissions from '@libs/Permissions';
import {isSelectedManagerMcTest} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Icon} from '@src/types/onyx/OnyxCommon';
import BaseListItem from './BaseListItem';
import type {InviteMemberListItemProps, ListItem} from './types';
Expand Down Expand Up @@ -48,10 +46,10 @@ function InviteMemberListItem<TItem extends ListItem>({
const theme = useTheme();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true});
const {isBetaEnabled} = usePermissions();
const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip} = useProductTrainingContext(
CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER,
!getIsUserSubmittedExpenseOrScannedReceipt() && Permissions.canUseManagerMcTest(betas) && isSelectedManagerMcTest(item.login) && !item.isSelected,
!getIsUserSubmittedExpenseOrScannedReceipt() && isBetaEnabled(CONST.BETAS.NEWDOT_MANAGER_MCTEST) && isSelectedManagerMcTest(item.login) && !item.isSelected,
);

const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor;
Expand Down
4 changes: 2 additions & 2 deletions src/components/SelectionList/Search/ReportListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function ReportListItem<TItem extends ListItem>({
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const {canUseTableReportView} = usePermissions();
const {isBetaEnabled} = usePermissions();
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {allowStaleData: true, initialValue: {}, canBeMissing: true});
const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem?.policyID}`];
const isEmptyReport = reportItem.transactions.length === 0;
Expand Down Expand Up @@ -83,7 +83,7 @@ function ReportListItem<TItem extends ListItem>({
return null;
}

if (isEmptyReport && !canUseTableReportView) {
if (isEmptyReport && !isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW)) {
return null;
}

Expand Down
9 changes: 6 additions & 3 deletions src/hooks/usePermissions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import {useContext, useMemo} from 'react';
import {BetasContext} from '@components/OnyxProvider';
import Permissions from '@libs/Permissions';
import type Beta from '@src/types/onyx/Beta';

type PermissionKey = keyof typeof Permissions;
type UsePermissions = Partial<Record<PermissionKey, boolean>>;
type UsePermissions = Partial<Record<Exclude<PermissionKey, 'isBetaEnabled'>, boolean>> & {isBetaEnabled: (beta: Beta) => boolean};
let permissionKey: PermissionKey;

export default function usePermissions(): UsePermissions {
const betas = useContext(BetasContext);
return useMemo(() => {
const permissions: UsePermissions = {};
const permissions: UsePermissions = {
isBetaEnabled: (beta: Beta) => Permissions.isBetaEnabled(beta, betas),
};

for (permissionKey in Permissions) {
if (betas) {
if (betas && permissionKey !== 'isBetaEnabled') {
const checkerFunction = Permissions[permissionKey];

permissions[permissionKey] = checkerFunction(betas);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Split = createSplitNavigator<ReportsSplitNavigatorParamList>();
* There can be multiple report screens in the stack with different report IDs.
*/
function ReportsSplitNavigator({route}: PlatformStackScreenProps<AuthScreensParamList, typeof NAVIGATORS.REPORTS_SPLIT_NAVIGATOR>) {
const {canUseDefaultRooms} = usePermissions();
const {isBetaEnabled} = usePermissions();
const splitNavigatorScreenOptions = useSplitNavigatorScreenOptions();

const [initialReportID] = useState(() => {
Expand All @@ -33,7 +33,7 @@ function ReportsSplitNavigator({route}: PlatformStackScreenProps<AuthScreensPara
return reportIdFromPath;
}

const initialReport = ReportUtils.findLastAccessedReport(!canUseDefaultRooms, shouldOpenOnAdminRoom());
const initialReport = ReportUtils.findLastAccessedReport(!isBetaEnabled(CONST.BETAS.DEFAULT_ROOMS), shouldOpenOnAdminRoom());
// eslint-disable-next-line rulesdir/no-default-id-values
return initialReport?.reportID ?? '';
});
Expand Down
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1721,7 +1721,7 @@ function getValidOptions(
[CONST.EMAIL.MANAGER_MCTEST]:
!canShowManagerMcTest ||
(getIsUserSubmittedExpenseOrScannedReceipt() && !userHasReportWithManagerMcTest) ||
!Permissions.canUseManagerMcTest(config.betas) ||
!Permissions.isBetaEnabled(CONST.BETAS.NEWDOT_MANAGER_MCTEST, config.betas) ||
isUserInvitedToWorkspace(),
};
// If we're including selected options from the search results, we only want to exclude them if the search input is empty
Expand Down
89 changes: 3 additions & 86 deletions src/libs/Permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,107 +6,24 @@ function canUseAllBetas(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.ALL);
}

function canUseDefaultRooms(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.DEFAULT_ROOMS) || canUseAllBetas(betas);
}

function isBlockedFromSpotnanaTravel(betas: OnyxEntry<Beta[]>): boolean {
// Don't check for all betas or nobody can use test travel on dev
return !!betas?.includes(CONST.BETAS.PREVENT_SPOTNANA_TRAVEL);
}

function isTravelVerified(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.IS_TRAVEL_VERIFIED) || canUseAllBetas(betas);
}

function canUseNetSuiteUSATax(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NETSUITE_USA_TAX) || canUseAllBetas(betas);
}

function canUseMultiLevelTags(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.MULTI_LEVEL_TAGS) || canUseAllBetas(betas);
}

/**
* Link previews are temporarily disabled.
*/
function canUseLinkPreviews(): boolean {
return false;
}

function canUseMergeAccounts(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEWDOT_MERGE_ACCOUNTS) || canUseAllBetas(betas);
}

function canUseManagerMcTest(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEWDOT_MANAGER_MCTEST) || canUseAllBetas(betas);
}

function canUseCustomRules(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.CUSTOM_RULES) || canUseAllBetas(betas);
}

/**
* The feature is released so hardcoding the value to true while we clean up the beta from the code.
*/
function canUseTableReportView(betas: OnyxEntry<Beta[]>): boolean {
return true || !!betas?.includes(CONST.BETAS.TABLE_REPORT_VIEW) || canUseAllBetas(betas);
}

function canUseTalkToAISales(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEW_DOT_TALK_TO_AI_SALES) || canUseAllBetas(betas);
}

function canUseInAppProvisioning(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.WALLET) || canUseAllBetas(betas);
}

function canUseGlobalReimbursementsOnND(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.GLOBAL_REIMBURSEMENTS_ON_ND) || canUseAllBetas(betas);
}

function canUsePlaidCompanyCards(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.PLAID_COMPANY_CARDS) || canUseAllBetas(betas);
}

function canUseRetractNewDot(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.RETRACT_NEWDOT) || canUseAllBetas(betas);
}

function canUseMultiScan(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEWDOT_MULTI_SCAN) || canUseAllBetas(betas);
}

function canUseMultiFilesDragAndDrop(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEWDOT_MULTI_FILES_DRAG_AND_DROP) || canUseAllBetas(betas);
}

function canUseTrackFlows(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.TRACK_FLOWS) || canUseAllBetas(betas);
}

function canUseNewDotSplits(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.NEW_DOT_SPLITS) || canUseAllBetas(betas);
function isBetaEnabled(beta: Beta, betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(beta) || canUseAllBetas(betas);
}

export default {
canUseDefaultRooms,
canUseLinkPreviews,
isBlockedFromSpotnanaTravel,
isTravelVerified,
canUseNetSuiteUSATax,
canUseMergeAccounts,
canUseManagerMcTest,
canUseCustomRules,
canUseTableReportView,
canUseTalkToAISales,
canUseInAppProvisioning,
canUseGlobalReimbursementsOnND,
canUseRetractNewDot,
canUseMultiLevelTags,
canUseMultiFilesDragAndDrop,
canUseMultiScan,
canUseNewDotSplits,
canUsePlaidCompanyCards,
canUseTrackFlows,
isBetaEnabled,
};
Loading