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
9 changes: 8 additions & 1 deletion src/components/TestDrive/TestDriveDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOffli
import EmbeddedDemo from '@components/EmbeddedDemo';
import Modal from '@components/Modal';
import SafeAreaConsumer from '@components/SafeAreaConsumer';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useOnboardingMessages from '@hooks/useOnboardingMessages';
import useOnyx from '@hooks/useOnyx';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import {completeTestDriveTask} from '@libs/actions/Task';
import Navigation from '@libs/Navigation/Navigation';
import {isPaidGroupPolicy, isUserPolicyAdmin} from '@libs/PolicyUtils';
import {isAdminRoom} from '@libs/ReportUtils';
import {getTestDriveURL} from '@libs/TourUtils';
import CONST from '@src/CONST';
Expand All @@ -25,6 +27,11 @@ function TestDriveDemo() {
const [onboardingReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${onboarding?.chatReportID}`, {canBeMissing: true});
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true});
const {testDrive} = useOnboardingMessages();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const [isPolicyAdmin = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {
canBeMissing: true,
selector: (policies) => Object.values(policies ?? {}).some((policy) => isPaidGroupPolicy(policy) && isUserPolicyAdmin(policy, currentUserPersonalDetails.login)),
});

useEffect(() => {
InteractionManager.runAfterInteractions(() => {
Expand Down Expand Up @@ -62,7 +69,7 @@ function TestDriveDemo() {
<TestDriveBanner onPress={closeModal} />
<FullPageOfflineBlockingView>
<EmbeddedDemo
url={getTestDriveURL(shouldUseNarrowLayout, introSelected)}
url={getTestDriveURL(shouldUseNarrowLayout, introSelected, isPolicyAdmin)}
iframeTitle={testDrive.EMBEDDED_DEMO_IFRAME_TITLE}
/>
</FullPageOfflineBlockingView>
Expand Down
17 changes: 12 additions & 5 deletions src/hooks/useOnboardingFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import {useEffect, useRef} from 'react';
import {InteractionManager} from 'react-native';
import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import Navigation from '@libs/Navigation/Navigation';
import Navigation, {navigationRef} from '@libs/Navigation/Navigation';
import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
import {buildCannedSearchQuery} from '@libs/SearchQueryUtils';
import {isLoggingInAsNewUser} from '@libs/SessionUtils';
import isProductTrainingElementDismissed from '@libs/TooltipUtils';
import CONFIG from '@src/CONFIG';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
Expand Down Expand Up @@ -61,11 +62,17 @@ function useOnboardingFlowRouter() {
if (CONFIG.IS_HYBRID_APP && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) {
return;
}

if (hasBeenAddedToNudgeMigration && !isProductTrainingElementDismissed('migratedUserWelcomeModal', dismissedProductTraining)) {
const defaultCannedQuery = buildCannedSearchQuery();
const query = defaultCannedQuery;
Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query}));
Navigation.navigate(ROUTES.MIGRATED_USER_WELCOME_MODAL.getRoute(true));
const navigationState = navigationRef.getRootState();
const lastRoute = navigationState.routes.at(-1);
// Prevent duplicate navigation if the migrated user modal is already shown.
if (lastRoute?.name !== NAVIGATORS.MIGRATED_USER_MODAL_NAVIGATOR) {
const defaultCannedQuery = buildCannedSearchQuery();
const query = defaultCannedQuery;
Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query}));
Navigation.navigate(ROUTES.MIGRATED_USER_WELCOME_MODAL.getRoute(true));
}
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@
let activePolicyId: OnyxEntry<string>;
let isLoadingReportData = true;

Onyx.connect({

Check warning on line 62 in src/libs/PolicyUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (value) => (allPolicies = value),
});

Onyx.connect({

Check warning on line 68 in src/libs/PolicyUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ACTIVE_POLICY_ID,
callback: (value) => (activePolicyId = value),
});

Onyx.connect({

Check warning on line 73 in src/libs/PolicyUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.IS_LOADING_REPORT_DATA,
initWithStoredValues: false,
callback: (value) => (isLoadingReportData = value ?? false),
Expand Down Expand Up @@ -311,7 +311,7 @@
/**
* Checks if the user with login is an admin of the policy.
*/
const isUserPolicyAdmin = (policy: OnyxInputOrEntry<Policy>, login?: string) => !!(policy && policy.employeeList && login && policy.employeeList[login]?.role === CONST.POLICY.ROLE.ADMIN);
const isUserPolicyAdmin = (policy: OnyxInputOrEntry<Policy>, login?: string) => getPolicyRole(policy, login) === CONST.POLICY.ROLE.ADMIN;

/**
* Checks if the current user is of the role "user" on the policy.
Expand Down
23 changes: 17 additions & 6 deletions src/libs/TourUtils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import type {OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import type {IntroSelected} from './actions/Report';

function getTestDriveURL(shouldUseNarrowLayout: boolean, introSelected?: IntroSelected) {
if (introSelected?.choice === CONST.ONBOARDING_CHOICES.SUBMIT && introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.WORKSPACE) {
return shouldUseNarrowLayout ? CONST.STORYLANE.EMPLOYEE_TOUR_MOBILE : CONST.STORYLANE.EMPLOYEE_TOUR;
function getTestDriveURL(shouldUseNarrowLayout: boolean, introSelected: OnyxEntry<IntroSelected>, isUserPolicyAdmin: boolean): string {
if (introSelected) {
if (introSelected?.choice === CONST.ONBOARDING_CHOICES.SUBMIT && introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.WORKSPACE) {
return shouldUseNarrowLayout ? CONST.STORYLANE.EMPLOYEE_TOUR_MOBILE : CONST.STORYLANE.EMPLOYEE_TOUR;
}

if (introSelected?.choice === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE) {
return shouldUseNarrowLayout ? CONST.STORYLANE.TRACK_WORKSPACE_TOUR_MOBILE : CONST.STORYLANE.TRACK_WORKSPACE_TOUR;
}

return shouldUseNarrowLayout ? CONST.STORYLANE.ADMIN_TOUR_MOBILE : CONST.STORYLANE.ADMIN_TOUR;
}

if (introSelected?.choice === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE) {
return shouldUseNarrowLayout ? CONST.STORYLANE.TRACK_WORKSPACE_TOUR_MOBILE : CONST.STORYLANE.TRACK_WORKSPACE_TOUR;
// Migrated users don't have the introSelected NVP, so we must check if they are an Admin of any Workspace in order
// to show the Admin demo.
if (isUserPolicyAdmin) {
return shouldUseNarrowLayout ? CONST.STORYLANE.ADMIN_TOUR_MOBILE : CONST.STORYLANE.ADMIN_TOUR;
}

return shouldUseNarrowLayout ? CONST.STORYLANE.ADMIN_TOUR_MOBILE : CONST.STORYLANE.ADMIN_TOUR;
return shouldUseNarrowLayout ? CONST.STORYLANE.EMPLOYEE_TOUR_MOBILE : CONST.STORYLANE.EMPLOYEE_TOUR;
}

// eslint-disable-next-line import/prefer-default-export
Expand Down
26 changes: 26 additions & 0 deletions src/libs/actions/Tour.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {InteractionManager} from 'react-native';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type {IntroSelected} from './Report';
import {completeTestDriveTask} from './Task';

function startTestDrive(introSelected: IntroSelected | undefined, shouldUpdateSelfTourViewedOnlyLocally = false, hasUserBeenAddedToNudgeMigration = false) {
InteractionManager.runAfterInteractions(() => {
if (
hasUserBeenAddedToNudgeMigration ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TEST_DRIVE_RECEIVER ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE ||
(introSelected?.choice === CONST.ONBOARDING_CHOICES.SUBMIT && introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.WORKSPACE)
) {
completeTestDriveTask(shouldUpdateSelfTourViewedOnlyLocally);
Navigation.navigate(ROUTES.TEST_DRIVE_DEMO_ROOT);
} else {
Navigation.navigate(ROUTES.TEST_DRIVE_MODAL_ROOT.route);
}
});
}

// eslint-disable-next-line import/prefer-default-export
export {startTestDrive};
33 changes: 11 additions & 22 deletions src/pages/Search/EmptySearchView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useMemo, useRef, useState} from 'react';
// eslint-disable-next-line no-restricted-imports
import type {GestureResponderEvent, ImageStyle, Text as RNText, TextStyle, ViewStyle} from 'react-native';
import {InteractionManager, Linking, View} from 'react-native';
import {Linking, View} from 'react-native';
import type {OnyxCollection} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import BookTravelButton from '@components/BookTravelButton';
Expand All @@ -28,10 +28,10 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {startMoneyRequest} from '@libs/actions/IOU';
import {openOldDotLink} from '@libs/actions/Link';
import {createNewReport} from '@libs/actions/Report';
import {completeTestDriveTask} from '@libs/actions/Task';
import {startTestDrive} from '@libs/actions/Tour';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import Navigation from '@libs/Navigation/Navigation';
import {hasSeenTourSelector} from '@libs/onboardingSelectors';
import {hasSeenTourSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
import {areAllGroupPoliciesExpenseChatDisabled, getGroupPaidPoliciesWithExpenseChatEnabled, isPaidGroupPolicy} from '@libs/PolicyUtils';
import {generateReportID} from '@libs/ReportUtils';
import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
Expand Down Expand Up @@ -90,6 +90,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
canBeMissing: true,
});
const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {selector: tryNewDotOnyxSelector, canBeMissing: true});

const groupPoliciesWithChatEnabled = getGroupPaidPoliciesWithExpenseChatEnabled();

Expand Down Expand Up @@ -194,20 +195,8 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
}
}

const startTestDrive = () => {
InteractionManager.runAfterInteractions(() => {
if (
introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TEST_DRIVE_RECEIVER ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE ||
(introSelected?.choice === CONST.ONBOARDING_CHOICES.SUBMIT && introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.WORKSPACE)
) {
completeTestDriveTask();
Navigation.navigate(ROUTES.TEST_DRIVE_DEMO_ROOT);
} else {
Navigation.navigate(ROUTES.TEST_DRIVE_MODAL_ROOT.route);
}
});
const startTestDriveAction = () => {
startTestDrive(introSelected, false, tryNewDot?.hasBeenAddedToNudgeMigration);
};

// If we are grouping by reports, show a custom message rather than a type-specific message
Expand All @@ -229,7 +218,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
? [
{
buttonText: translate('emptySearchView.takeATestDrive'),
buttonAction: startTestDrive,
buttonAction: startTestDriveAction,
},
]
: []),
Expand Down Expand Up @@ -296,7 +285,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
? [
{
buttonText: translate('emptySearchView.takeATestDrive'),
buttonAction: startTestDrive,
buttonAction: startTestDriveAction,
},
]
: []),
Expand Down Expand Up @@ -327,7 +316,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
? [
{
buttonText: translate('emptySearchView.takeATestDrive'),
buttonAction: startTestDrive,
buttonAction: startTestDriveAction,
},
]
: []),
Expand Down Expand Up @@ -369,8 +358,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
styles.emptyStateFolderWebStyles,
styles.textAlignLeft,
styles.tripEmptyStateLottieWebView,
introSelected?.choice,
introSelected?.inviteType,
introSelected,
hasResults,
defaultViewItemHeader,
hasSeenTour,
Expand All @@ -381,6 +369,7 @@ function EmptySearchView({hash, type, groupBy, hasResults}: EmptySearchViewProps
tripViewChildren,
shouldRedirectToExpensifyClassic,
transactions,
tryNewDot?.hasBeenAddedToNudgeMigration,
]);

return (
Expand Down
24 changes: 5 additions & 19 deletions src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Str} from 'expensify-common';
import type {ImageContentFit} from 'expo-image';
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import {View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import ConfirmModal from '@components/ConfirmModal';
import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider';
Expand All @@ -27,13 +27,13 @@ import {openOldDotLink} from '@libs/actions/Link';
import {navigateToQuickAction} from '@libs/actions/QuickActionNavigation';
import {createNewReport, startNewChat} from '@libs/actions/Report';
import {isAnonymousUser} from '@libs/actions/Session';
import {completeTestDriveTask} from '@libs/actions/Task';
import {startTestDrive} from '@libs/actions/Tour';
import getIconForAction from '@libs/getIconForAction';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import navigateAfterInteraction from '@libs/Navigation/navigateAfterInteraction';
import Navigation from '@libs/Navigation/Navigation';
import {hasSeenTourSelector} from '@libs/onboardingSelectors';
import {hasSeenTourSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
import {openTravelDotLink, shouldOpenTravelDotLinkWeb} from '@libs/openTravelDotLink';
import {
areAllGroupPoliciesExpenseChatDisabled,
Expand Down Expand Up @@ -135,6 +135,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, isT
selector: hasSeenTourSelector,
canBeMissing: true,
});
const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {selector: tryNewDotOnyxSelector, canBeMissing: true});

const groupPoliciesWithChatEnabled = getGroupPaidPoliciesWithExpenseChatEnabled();

Expand Down Expand Up @@ -525,22 +526,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, isT
iconStyles: styles.popoverIconCircle,
iconFill: theme.icon,
text: translate('testDrive.quickAction.takeATwoMinuteTestDrive'),
onSelected: () =>
interceptAnonymousUser(() => {
InteractionManager.runAfterInteractions(() => {
if (
introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TEST_DRIVE_RECEIVER ||
introSelected?.choice === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE ||
(introSelected?.choice === CONST.ONBOARDING_CHOICES.SUBMIT && introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.WORKSPACE)
) {
completeTestDriveTask(isAnonymousUser());
Navigation.navigate(ROUTES.TEST_DRIVE_DEMO_ROOT);
} else {
Navigation.navigate(ROUTES.TEST_DRIVE_MODAL_ROOT.route);
}
});
}),
onSelected: () => interceptAnonymousUser(() => startTestDrive(introSelected, isAnonymousUser(), tryNewDot?.hasBeenAddedToNudgeMigration)),
},
]
: []),
Expand Down
Loading
Loading