diff --git a/src/CONST.ts b/src/CONST.ts index 74d04163518e9..6590b672fe353 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6695,8 +6695,6 @@ const CONST = { LHN_WORKSPACE_CHAT_TOOLTIP: 'workspaceChatLHNTooltip', GLOBAL_CREATE_TOOLTIP: 'globalCreateTooltip', SCAN_TEST_TOOLTIP: 'scanTestTooltip', - SCAN_TEST_TOOLTIP_MANAGER: 'scanTestTooltipManager', - SCAN_TEST_CONFIRMATION: 'scanTestConfirmation', }, SMART_BANNER_HEIGHT: 152, diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 37ab583a11e31..050f2a6e403b1 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -31,8 +31,7 @@ import {calculateAmount, insertTagIntoTransactionTagsString, isMovingTransaction import Log from '@libs/Log'; import {validateAmount} from '@libs/MoneyRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getIOUConfirmationOptionsFromPayeePersonalDetail, hasEnabledOptions, isSelectedManagerMcTest} from '@libs/OptionsListUtils'; -import Permissions from '@libs/Permissions'; +import {getIOUConfirmationOptionsFromPayeePersonalDetail, hasEnabledOptions} from '@libs/OptionsListUtils'; import {getDistanceRateCustomUnitRate, getTagLists, isTaxTrackingEnabled} from '@libs/PolicyUtils'; import type {OptionData} from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; @@ -66,13 +65,11 @@ import FormHelpMessage from './FormHelpMessage'; import MoneyRequestAmountInput from './MoneyRequestAmountInput'; import MoneyRequestConfirmationListFooter from './MoneyRequestConfirmationListFooter'; import {PressableWithFeedback} from './Pressable'; -import {useProductTrainingContext} from './ProductTrainingContext'; import SelectionList from './SelectionList'; import type {SectionListDataType} from './SelectionList/types'; import UserListItem from './SelectionList/UserListItem'; import SettlementButton from './SettlementButton'; import Text from './Text'; -import EducationalTooltip from './Tooltip/EducationalTooltip'; type MoneyRequestConfirmationListProps = { /** Callback to inform parent modal of success */ @@ -218,11 +215,6 @@ function MoneyRequestConfirmationList({ const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${policyID}`); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES); const [currencyList] = useOnyx(ONYXKEYS.CURRENCY_LIST); - const [betas] = useOnyx(ONYXKEYS.BETAS); - const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip} = useProductTrainingContext( - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_CONFIRMATION, - Permissions.canUseManagerMcTest(betas) && selectedParticipantsProp.some((participant) => isSelectedManagerMcTest(participant.login)), - ); const policy = policyReal ?? policyDraft; const policyCategories = policyCategoriesReal ?? policyCategoriesDraft; @@ -974,37 +966,11 @@ function MoneyRequestConfirmationList({ message={errorMessage} /> )} - - {button} - + + {button} ); - }, [ - isReadOnly, - iouType, - confirm, - bankAccountRoute, - iouCurrencyCode, - policyID, - isConfirmed, - splitOrRequestOptions, - errorMessage, - styles.ph1, - styles.mb2, - styles.productTrainingTooltipWrapper, - shouldShowProductTrainingTooltip, - renderProductTrainingTooltip, - ]); + }, [isReadOnly, iouType, confirm, isConfirmed, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, styles.ph1, styles.mb2, errorMessage]); const listFooterContent = ( ; @@ -121,34 +119,18 @@ const TOOLTIPS: Record = { content: [ {text: 'productTrainingTooltip.scanTestTooltip.part1', isBold: false}, {text: 'productTrainingTooltip.scanTestTooltip.part2', isBold: true}, - ], - onHideTooltip: () => dismissProductTraining(SCAN_TEST_TOOLTIP), - name: SCAN_TEST_TOOLTIP, - priority: 900, - shouldShow: () => true, - shouldRenderActionButtons: true, - }, - [SCAN_TEST_TOOLTIP_MANAGER]: { - content: [ {text: 'productTrainingTooltip.scanTestTooltip.part3', isBold: false}, {text: 'productTrainingTooltip.scanTestTooltip.part4', isBold: true}, {text: 'productTrainingTooltip.scanTestTooltip.part5', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER), - name: SCAN_TEST_TOOLTIP_MANAGER, - priority: 1000, - shouldShow: () => true, - }, - [SCAN_TEST_CONFIRMATION]: { - content: [ {text: 'productTrainingTooltip.scanTestTooltip.part6', isBold: false}, {text: 'productTrainingTooltip.scanTestTooltip.part7', isBold: true}, {text: 'productTrainingTooltip.scanTestTooltip.part8', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(SCAN_TEST_CONFIRMATION), - name: SCAN_TEST_CONFIRMATION, - priority: 1100, - shouldShow: () => true, + onHideTooltip: () => dismissProductTraining(SCAN_TEST_TOOLTIP), + name: SCAN_TEST_TOOLTIP, + priority: 900, + shouldShow: () => false, + shouldRenderActionButtons: true, }, }; diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index 8bb3c20572c99..8205529014522 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -101,13 +101,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { } // We need to make an exception for the QAB tooltip because it is shown in a modal, otherwise it would be hidden if a modal is visible - if ( - tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.QUICK_ACTION_BUTTON && - tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP && - tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER && - tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_CONFIRMATION && - isModalVisible - ) { + if (tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.QUICK_ACTION_BUTTON && isModalVisible) { return false; } @@ -137,6 +131,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { return false; } const visibleTooltip = determineVisibleTooltip(); + // If this is the highest priority visible tooltip, show it if (tooltipName === visibleTooltip) { return true; @@ -254,6 +249,7 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou const shouldShowProductTrainingTooltip = useMemo(() => { return shouldShow && shouldRenderTooltip(tooltipName); }, [shouldRenderTooltip, tooltipName, shouldShow]); + const hideProductTrainingTooltip = useCallback(() => { if (!shouldShowProductTrainingTooltip) { return; diff --git a/src/components/SelectionList/InviteMemberListItem.tsx b/src/components/SelectionList/InviteMemberListItem.tsx index d399ff8ade657..7442fe24f7d23 100644 --- a/src/components/SelectionList/InviteMemberListItem.tsx +++ b/src/components/SelectionList/InviteMemberListItem.tsx @@ -1,24 +1,18 @@ 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'; -import {useProductTrainingContext} from '@components/ProductTrainingContext'; import SelectCircle from '@components/SelectCircle'; import SubscriptAvatar from '@components/SubscriptAvatar'; import Text from '@components/Text'; import TextWithTooltip from '@components/TextWithTooltip'; -import EducationalTooltip from '@components/Tooltip/EducationalTooltip'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import {getIsUserSubmittedExpenseOrScannedReceipt, isSelectedManagerMcTest} from '@libs/OptionsListUtils'; -import Permissions from '@libs/Permissions'; 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'; @@ -48,11 +42,6 @@ function InviteMemberListItem({ const theme = useTheme(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); - const [betas] = useOnyx(ONYXKEYS.BETAS); - const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip} = useProductTrainingContext( - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER, - !getIsUserSubmittedExpenseOrScannedReceipt() && Permissions.canUseManagerMcTest(betas) && isSelectedManagerMcTest(item.login), - ); const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; const subscriptAvatarBorderColor = isFocused ? focusedBackgroundColor : theme.sidebar; @@ -95,75 +84,64 @@ function InviteMemberListItem({ shouldDisplayRBR={!shouldShowCheckBox} > {(hovered?: boolean) => ( - - - {!!item.icons && - (item.shouldShowSubscript ? ( - - ) : ( - - ))} - - - - - {!!item.alternateText && ( - - )} + <> + {!!item.icons && + (item.shouldShowSubscript ? ( + + ) : ( + + ))} + + + - {!!item.rightElement && item.rightElement} - {!!shouldShowCheckBox && ( - - - + {!!item.alternateText && ( + )} - + {!!item.rightElement && item.rightElement} + {!!shouldShowCheckBox && ( + + + + )} + )} ); diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index 1813ef21f0a83..cc35dc4827424 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -1,17 +1,13 @@ import type {MaterialTopTabBarProps} from '@react-navigation/material-top-tabs/lib/typescript/src/types'; import React, {useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; import FocusTrapContainerElement from '@components/FocusTrap/FocusTrapContainerElement'; import * as Expensicons from '@components/Icon/Expensicons'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import {getIsUserSubmittedExpenseOrScannedReceipt} from '@libs/OptionsListUtils'; -import Permissions from '@libs/Permissions'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import type IconAsset from '@src/types/utils/IconAsset'; import getBackgroundColor from './getBackground'; import getOpacity from './getOpacity'; @@ -58,7 +54,6 @@ function TabSelector({state, navigation, onTabPress = () => {}, position, onFocu const styles = useThemeStyles(); const defaultAffectedAnimatedTabs = useMemo(() => Array.from({length: state.routes.length}, (v, i) => i), [state.routes.length]); const [affectedAnimatedTabs, setAffectedAnimatedTabs] = useState(defaultAffectedAnimatedTabs); - const [betas] = useOnyx(ONYXKEYS.BETAS); useEffect(() => { // It is required to wait transition end to reset affectedAnimatedTabs because tabs style is still animating during transition. @@ -76,8 +71,7 @@ function TabSelector({state, navigation, onTabPress = () => {}, position, onFocu const inactiveOpacity = getOpacity({routesLength: state.routes.length, tabIndex: index, active: false, affectedTabs: affectedAnimatedTabs, position, isActive}); const backgroundColor = getBackgroundColor({routesLength: state.routes.length, tabIndex: index, affectedTabs: affectedAnimatedTabs, theme, position, isActive}); const {icon, title} = getIconAndTitle(route.name, translate); - const shouldShowTestReceiptTooltip = - route.name === CONST.TAB_REQUEST.SCAN && isActive && !getIsUserSubmittedExpenseOrScannedReceipt() && Permissions.canUseManagerMcTest(betas); + const onPress = () => { if (isActive) { return; @@ -110,7 +104,6 @@ function TabSelector({state, navigation, onTabPress = () => {}, position, onFocu backgroundColor={backgroundColor} isActive={isActive} shouldShowLabelWhenInactive={shouldShowLabelWhenInactive} - shouldShowTestReceiptTooltip={shouldShowTestReceiptTooltip} /> ); })} @@ -120,6 +113,7 @@ function TabSelector({state, navigation, onTabPress = () => {}, position, onFocu } TabSelector.displayName = 'TabSelector'; + export default TabSelector; export type {TabSelectorProps}; diff --git a/src/components/TabSelector/TabSelectorItem.tsx b/src/components/TabSelector/TabSelectorItem.tsx index b3daba89b7e57..b5d067d410c3b 100644 --- a/src/components/TabSelector/TabSelectorItem.tsx +++ b/src/components/TabSelector/TabSelectorItem.tsx @@ -2,9 +2,7 @@ import React, {useState} from 'react'; // eslint-disable-next-line no-restricted-imports import {Animated} from 'react-native'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; -import {useProductTrainingContext} from '@components/ProductTrainingContext'; import Tooltip from '@components/Tooltip'; -import EducationalTooltip from '@components/Tooltip/EducationalTooltip'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -37,9 +35,6 @@ type TabSelectorItemProps = { /** Whether to show the label when the tab is inactive */ shouldShowLabelWhenInactive?: boolean; - - /** Whether to show the test receipt tooltip */ - shouldShowTestReceiptTooltip?: boolean; }; function TabSelectorItem({ @@ -51,14 +46,15 @@ function TabSelectorItem({ inactiveOpacity = 1, isActive = false, shouldShowLabelWhenInactive = true, - shouldShowTestReceiptTooltip = false, }: TabSelectorItemProps) { const styles = useThemeStyles(); const [isHovered, setIsHovered] = useState(false); - const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip} = useProductTrainingContext(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP, shouldShowTestReceiptTooltip); - const content = () => { - return ( + return ( + )} - ); - }; - - return shouldShowTestReceiptTooltip ? ( - - {content()} - - ) : ( - - {content()} ); } diff --git a/src/languages/en.ts b/src/languages/en.ts index e87d266321ac3..68e1649e1fa06 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5951,7 +5951,7 @@ const translations = { part5: ' to try it out!', part6: 'Now,', part7: ' submit your expense', - part8: ' and watch the\nmagic happen!', + part8: ' and watch the magic happen!', tryItOut: 'Try it out', noThanks: 'No thanks', }, diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index ee63e0f553415..a18300f593b8a 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1485,7 +1485,7 @@ function getValidOptions( [CONST.EMAIL.NOTIFICATIONS]: true, ...excludeLogins, // Exclude Manager McTest if user submitted expense or scanned receipt and when selection is made from Create or Submit flow - [CONST.EMAIL.MANAGER_MCTEST]: !(!getIsUserSubmittedExpenseOrScannedReceipt() && canShowManagerMcTest && Permissions.canUseManagerMcTest(config.betas)), + [CONST.EMAIL.MANAGER_MCTEST]: !(Permissions.canUseManagerMcTest(config.betas) && !getIsUserSubmittedExpenseOrScannedReceipt() && canShowManagerMcTest), }; // If we're including selected options from the search results, we only want to exclude them if the search input is empty // This is because on certain pages, we show the selected options at the top when the search input is empty @@ -2148,13 +2148,6 @@ function shouldUseBoldText(report: OptionData): boolean { return report.isUnread === true && notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE && !isHiddenForCurrentUser(notificationPreference); } -/** - * Helper method to check if participant email is Manager McTest - */ -function isSelectedManagerMcTest(email: string | null | undefined): boolean { - return email === CONST.EMAIL.MANAGER_MCTEST; -} - export { getAvatarsForAccountIDs, isCurrentUser, @@ -2208,8 +2201,6 @@ export { orderWorkspaceOptions, filterSelfDMChat, filterReports, - getIsUserSubmittedExpenseOrScannedReceipt, - isSelectedManagerMcTest, }; export type {Section, SectionBase, MemberForList, Options, OptionList, SearchOption, PayeePersonalDetails, Option, OptionTree, ReportAndPersonalDetailOptions, GetUserToInviteConfig}; diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index ae6079b4b632d..0ab9425398bd9 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -10,8 +10,6 @@ const { LHN_WORKSPACE_CHAT_TOOLTIP, GLOBAL_CREATE_TOOLTIP, SCAN_TEST_TOOLTIP, - SCAN_TEST_TOOLTIP_MANAGER, - SCAN_TEST_CONFIRMATION, } = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; /** * This type is used to store the timestamp of when the user dismisses a product training ui elements. @@ -66,16 +64,6 @@ type DismissedProductTraining = { * When user dismisses the globalCreateTooltip product training tooltip, we store the timestamp here. */ [SCAN_TEST_TOOLTIP]: string; - - /** - * When user dismisses the test manager tooltip product training tooltip, we store the timestamp here. - */ - [SCAN_TEST_TOOLTIP_MANAGER]: string; - - /** - * When user dismisses the test manager on confirmantion page product training tooltip, we store the timestamp here. - */ - [SCAN_TEST_CONFIRMATION]: string; }; export default DismissedProductTraining; diff --git a/tests/ui/components/TabSelectorItem.tsx b/tests/ui/components/TabSelectorItem.tsx index 0e595a6103194..5fb0274a38c4d 100644 --- a/tests/ui/components/TabSelectorItem.tsx +++ b/tests/ui/components/TabSelectorItem.tsx @@ -5,12 +5,6 @@ import Tooltip from '@components/Tooltip'; // Mock the Tooltip component since it uses portals which aren't supported in RNTL jest.mock('@components/Tooltip'); -jest.mock('@libs/Fullstory', () => ({ - default: { - consentAndIdentify: jest.fn(), - }, - parseFSAttributes: jest.fn(), -})); describe('TabSelectorItem Component', () => { const title = 'Test Tab';