diff --git a/src/App.tsx b/src/App.tsx index cc824b78fa4c..52904e0a06c4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,7 +18,6 @@ import KeyboardProvider from './components/KeyboardProvider'; import {LocaleContextProvider} from './components/LocaleContextProvider'; import OnyxProvider from './components/OnyxProvider'; import PopoverContextProvider from './components/PopoverProvider'; -import {ProductTrainingContextProvider} from './components/ProductTrainingContext'; import SafeArea from './components/SafeArea'; import ScrollOffsetContextProvider from './components/ScrollOffsetContextProvider'; import {SearchRouterContextProvider} from './components/Search/SearchRouter/SearchRouterContext'; @@ -96,7 +95,6 @@ function App({url}: AppProps) { VideoPopoverMenuContextProvider, KeyboardProvider, SearchRouterContextProvider, - ProductTrainingContextProvider, ]} > diff --git a/src/CONST.ts b/src/CONST.ts index 5d2331b6b304..4bfaad7b6d1b 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6437,17 +6437,6 @@ const CONST = { }, MIGRATED_USER_WELCOME_MODAL: 'migratedUserWelcomeModal', - - PRODUCT_TRAINING_TOOLTIP_NAMES: { - CONCEIRGE_LHN_GBR: 'conciergeLHNGBR', - RENAME_SAVED_SEARCH: 'renameSavedSearch', - QUICK_ACTION_BUTTON: 'quickActionButton', - WORKSAPCE_CHAT_CREATE: 'workspaceChatCreate', - SEARCH_FILTER_BUTTON_TOOLTIP: 'filterButtonTooltip', - BOTTOM_NAV_INBOX_TOOLTIP: 'bottomNavInboxTooltip', - LHN_WORKSPACE_CHAT_TOOLTIP: 'workspaceChatLHNTooltip', - GLOBAL_CREATE_TOOLTIP: 'globalCreateTooltip', - }, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index cdb21373a2cf..462ca9e22d2d 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -117,6 +117,9 @@ const ONYXKEYS = { /** NVP keys */ + /** Boolean flag only true when first set */ + NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER: 'nvp_isFirstTimeNewExpensifyUser', + /** This NVP contains list of at most 5 recent attendees */ NVP_RECENT_ATTENDEES: 'nvp_expensify_recentAttendees', @@ -219,9 +222,18 @@ const ONYXKEYS = { /** The end date (epoch timestamp) of the workspace owner’s grace period after the free trial ends. */ NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END: 'nvp_private_billingGracePeriodEnd', + /** The NVP containing all information related to educational tooltip in workspace chat */ + NVP_WORKSPACE_TOOLTIP: 'workspaceTooltip', + /** The NVP containing the target url to navigate to when deleting a transaction */ NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL: 'nvp_deleteTransactionNavigateBackURL', + /** Whether to show save search rename tooltip */ + SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP: 'shouldShowSavedSearchRenameTooltip', + + /** Whether to hide gbr tooltip */ + NVP_SHOULD_HIDE_GBR_TOOLTIP: 'nvp_should_hide_gbr_tooltip', + /** Does this user have push notifications enabled for this device? */ PUSH_NOTIFICATIONS_ENABLED: 'pushNotificationsEnabled', @@ -870,6 +882,7 @@ type OnyxCollectionValuesMapping = { type OnyxValuesMapping = { [ONYXKEYS.ACCOUNT]: OnyxTypes.Account; [ONYXKEYS.ACCOUNT_MANAGER_REPORT_ID]: string; + [ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER]: boolean; // NVP_ONBOARDING is an array for old users. [ONYXKEYS.NVP_ONBOARDING]: Onboarding | []; @@ -1012,7 +1025,9 @@ type OnyxValuesMapping = { [ONYXKEYS.NVP_BILLING_FUND_ID]: number; [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: number; [ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END]: number; + [ONYXKEYS.NVP_WORKSPACE_TOOLTIP]: OnyxTypes.WorkspaceTooltip; [ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL]: string | undefined; + [ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP]: boolean; [ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[]; [ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string; [ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx; @@ -1020,6 +1035,7 @@ type OnyxValuesMapping = { [ONYXKEYS.LAST_ROUTE]: string; [ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY]: boolean | undefined; [ONYXKEYS.IS_USING_IMPORTED_STATE]: boolean; + [ONYXKEYS.SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP]: boolean; [ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES]: Record; [ONYXKEYS.CONCIERGE_REPORT_ID]: string; [ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING]: OnyxTypes.DismissedProductTraining; diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx index e0f0ff4e6dcd..3c831301db8b 100644 --- a/src/components/FloatingActionButton.tsx +++ b/src/components/FloatingActionButton.tsx @@ -5,16 +5,10 @@ import type {GestureResponderEvent, Role, Text, View} from 'react-native'; import {Platform} from 'react-native'; import Animated, {createAnimatedPropAdapter, Easing, interpolateColor, processColor, useAnimatedProps, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import Svg, {Path} from 'react-native-svg'; -import useBottomTabIsFocused from '@hooks/useBottomTabIsFocused'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import getPlatform from '@libs/getPlatform'; import variables from '@styles/variables'; -import CONST from '@src/CONST'; import {PressableWithoutFeedback} from './Pressable'; -import {useProductTrainingContext} from './ProductTrainingContext'; -import EducationalTooltip from './Tooltip/EducationalTooltip'; const AnimatedPath = Animated.createAnimatedComponent(Path); AnimatedPath.displayName = 'AnimatedPath'; @@ -62,14 +56,6 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo const styles = useThemeStyles(); const borderRadius = styles.floatingActionButton.borderRadius; const fabPressable = useRef(null); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - const platform = getPlatform(); - const isNarrowScreenOnWeb = shouldUseNarrowLayout && platform === CONST.PLATFORM.WEB; - const isFocused = useBottomTabIsFocused(); - const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext( - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP, - isFocused, - ); const sharedValue = useSharedValue(isActive ? 1 : 0); const buttonRef = ref; @@ -111,45 +97,32 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo }; return ( - { + fabPressable.current = el ?? null; + if (buttonRef && 'current' in buttonRef) { + buttonRef.current = el ?? null; + } }} - shouldUseOverlay - shiftHorizontal={isNarrowScreenOnWeb ? 0 : variables.fabTooltipShiftHorizontal} - renderTooltipContent={renderProductTrainingTooltip} - wrapperStyle={styles.productTrainingTooltipWrapper} - onHideTooltip={hideProductTrainingTooltip} + style={[styles.h100, styles.bottomTabBarItem]} + accessibilityLabel={accessibilityLabel} + onPress={toggleFabAction} + onLongPress={() => {}} + role={role} + shouldUseHapticsOnLongPress={false} > - { - fabPressable.current = el ?? null; - if (buttonRef && 'current' in buttonRef) { - buttonRef.current = el ?? null; - } - }} - style={[styles.h100, styles.bottomTabBarItem]} - accessibilityLabel={accessibilityLabel} - onPress={toggleFabAction} - onLongPress={() => {}} - role={role} - shouldUseHapticsOnLongPress={false} - > - - - - - - - + + + + + + ); } diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index efdd9659c845..c423d3101d92 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -1,5 +1,5 @@ import {useFocusEffect} from '@react-navigation/native'; -import React, {useCallback, useMemo, useRef, useState} from 'react'; +import React, {useCallback, useRef, useState} from 'react'; import type {GestureResponderEvent, ViewStyle} from 'react-native'; import {StyleSheet, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -11,7 +11,6 @@ import MultipleAvatars from '@components/MultipleAvatars'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {useSession} from '@components/OnyxProvider'; import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; -import {useProductTrainingContext} from '@components/ProductTrainingContext'; import SubscriptAvatar from '@components/SubscriptAvatar'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; @@ -23,6 +22,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import DomUtils from '@libs/DomUtils'; +import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; import Performance from '@libs/Performance'; @@ -32,6 +32,7 @@ import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportA import FreeTrial from '@pages/settings/Subscription/FreeTrial'; import variables from '@styles/variables'; import Timing from '@userActions/Timing'; +import * as User from '@userActions/User'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -47,21 +48,18 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${optionItem?.reportID || -1}`); - const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); - const isActiveWorkspaceChat = ReportUtils.isPolicyExpenseChat(report) && report?.isOwnPolicyExpenseChat && activePolicyID === report?.policyID; + const [isFirstTimeNewExpensifyUser] = useOnyx(ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER); + const [isOnboardingCompleted = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { + selector: hasCompletedGuidedSetupFlowSelector, + }); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const session = useSession(); - const isOnboardingGuideAssigned = introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM && !session?.email?.includes('+'); - const shouldShowGetStartedTooltip = isOnboardingGuideAssigned ? ReportUtils.isAdminRoom(report) : ReportUtils.isConciergeChatReport(report); - - const {tooltipToRender, shouldShowTooltip} = useMemo(() => { - const tooltip = shouldShowGetStartedTooltip ? CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR : CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - return {tooltipToRender: tooltip, shouldShowTooltip: shouldUseNarrowLayout ? isScreenFocused : true}; - }, [shouldShowGetStartedTooltip, isScreenFocused, shouldUseNarrowLayout]); + // Guides are assigned for the MANAGE_TEAM onboarding action, except for emails that have a '+'. + const isOnboardingGuideAssigned = introSelected?.choice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM && !session?.email?.includes('+'); + const shouldShowToooltipOnThisReport = isOnboardingGuideAssigned ? ReportUtils.isAdminRoom(report) : ReportUtils.isConciergeChatReport(report); + const [shouldHideGBRTooltip] = useOnyx(ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP, {initialValue: true}); - const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext(tooltipToRender, shouldShowTooltip); const {translate} = useLocalize(); const [isContextMenuActive, setIsContextMenuActive] = useState(false); @@ -74,6 +72,30 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti }, []), ); + const renderGBRTooltip = useCallback( + () => ( + + + {translate('sidebarScreen.tooltip')} + + ), + [ + styles.alignItemsCenter, + styles.flexRow, + styles.justifyContentCenter, + styles.flexWrap, + styles.textAlignCenter, + styles.gap1, + styles.quickActionTooltipSubtitle, + theme.tooltipHighlightText, + translate, + ], + ); + const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT; const sidebarInnerRowStyle = StyleSheet.flatten( isInFocusMode @@ -158,18 +180,17 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti needsOffscreenAlphaCompositing > diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts deleted file mode 100644 index dc2a761a4903..000000000000 --- a/src/components/ProductTrainingContext/TOOLTIPS.ts +++ /dev/null @@ -1,118 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import {dismissProductTraining} from '@libs/actions/Welcome'; -import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; - -const { - CONCEIRGE_LHN_GBR, - RENAME_SAVED_SEARCH, - WORKSAPCE_CHAT_CREATE, - QUICK_ACTION_BUTTON, - SEARCH_FILTER_BUTTON_TOOLTIP, - BOTTOM_NAV_INBOX_TOOLTIP, - LHN_WORKSPACE_CHAT_TOOLTIP, - GLOBAL_CREATE_TOOLTIP, -} = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; - -type ProductTrainingTooltipName = ValueOf; - -type ShouldShowConditionProps = { - shouldUseNarrowLayout?: boolean; -}; - -type TooltipData = { - content: Array<{text: TranslationPaths; isBold: boolean}>; - onHideTooltip: () => void; - name: ProductTrainingTooltipName; - priority: number; - shouldShow: (props: ShouldShowConditionProps) => boolean; -}; - -const TOOLTIPS: Record = { - [CONCEIRGE_LHN_GBR]: { - content: [ - {text: 'productTrainingTooltip.conciergeLHNGBR.part1', isBold: false}, - {text: 'productTrainingTooltip.conciergeLHNGBR.part2', isBold: true}, - ], - onHideTooltip: () => dismissProductTraining(CONCEIRGE_LHN_GBR), - name: CONCEIRGE_LHN_GBR, - priority: 1300, - shouldShow: ({shouldUseNarrowLayout}) => !!shouldUseNarrowLayout, - }, - [RENAME_SAVED_SEARCH]: { - content: [ - {text: 'productTrainingTooltip.saveSearchTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.saveSearchTooltip.part2', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(RENAME_SAVED_SEARCH), - name: RENAME_SAVED_SEARCH, - priority: 1250, - shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout, - }, - [GLOBAL_CREATE_TOOLTIP]: { - content: [ - {text: 'productTrainingTooltip.globalCreateTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.globalCreateTooltip.part2', isBold: false}, - {text: 'productTrainingTooltip.globalCreateTooltip.part3', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(GLOBAL_CREATE_TOOLTIP), - name: GLOBAL_CREATE_TOOLTIP, - priority: 1200, - shouldShow: () => true, - }, - [QUICK_ACTION_BUTTON]: { - content: [ - {text: 'productTrainingTooltip.quickActionButton.part1', isBold: true}, - {text: 'productTrainingTooltip.quickActionButton.part2', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(QUICK_ACTION_BUTTON), - name: QUICK_ACTION_BUTTON, - priority: 1150, - shouldShow: () => true, - }, - [WORKSAPCE_CHAT_CREATE]: { - content: [ - {text: 'productTrainingTooltip.workspaceChatCreate.part1', isBold: true}, - {text: 'productTrainingTooltip.workspaceChatCreate.part2', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(WORKSAPCE_CHAT_CREATE), - name: WORKSAPCE_CHAT_CREATE, - priority: 1100, - shouldShow: () => true, - }, - [SEARCH_FILTER_BUTTON_TOOLTIP]: { - content: [ - {text: 'productTrainingTooltip.searchFilterButtonTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.searchFilterButtonTooltip.part2', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(SEARCH_FILTER_BUTTON_TOOLTIP), - name: SEARCH_FILTER_BUTTON_TOOLTIP, - priority: 1000, - shouldShow: () => true, - }, - [BOTTOM_NAV_INBOX_TOOLTIP]: { - content: [ - {text: 'productTrainingTooltip.bottomNavInboxTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: false}, - {text: 'productTrainingTooltip.bottomNavInboxTooltip.part3', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP), - name: BOTTOM_NAV_INBOX_TOOLTIP, - priority: 900, - shouldShow: () => true, - }, - [LHN_WORKSPACE_CHAT_TOOLTIP]: { - content: [ - {text: 'productTrainingTooltip.workspaceChatTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: false}, - {text: 'productTrainingTooltip.workspaceChatTooltip.part3', isBold: false}, - ], - onHideTooltip: () => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP), - name: LHN_WORKSPACE_CHAT_TOOLTIP, - priority: 800, - shouldShow: () => true, - }, -}; - -export default TOOLTIPS; -export type {ProductTrainingTooltipName}; diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx deleted file mode 100644 index 7cfcf4d3bfa7..000000000000 --- a/src/components/ProductTrainingContext/index.tsx +++ /dev/null @@ -1,224 +0,0 @@ -import React, {createContext, useCallback, useContext, useEffect, useMemo, useState} from 'react'; -import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; -import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type ChildrenProps from '@src/types/utils/ChildrenProps'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import type {ProductTrainingTooltipName} from './TOOLTIPS'; -import TOOLTIPS from './TOOLTIPS'; - -type ProductTrainingContextType = { - shouldRenderTooltip: (tooltipName: ProductTrainingTooltipName) => boolean; - registerTooltip: (tooltipName: ProductTrainingTooltipName) => void; - unregisterTooltip: (tooltipName: ProductTrainingTooltipName) => void; -}; - -const ProductTrainingContext = createContext({ - shouldRenderTooltip: () => false, - registerTooltip: () => {}, - unregisterTooltip: () => {}, -}); - -function ProductTrainingContextProvider({children}: ChildrenProps) { - const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT); - const hasBeenAddedToNudgeMigration = !!tryNewDot?.nudgeMigration?.timestamp; - const [isOnboardingCompleted = true, isOnboardingCompletedMetadata] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { - selector: hasCompletedGuidedSetupFlowSelector, - }); - const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - - const [activeTooltips, setActiveTooltips] = useState>(new Set()); - - const unregisterTooltip = useCallback( - (tooltipName: ProductTrainingTooltipName) => { - setActiveTooltips((prev) => { - const next = new Set(prev); - next.delete(tooltipName); - return next; - }); - }, - [setActiveTooltips], - ); - - const determineVisibleTooltip = useCallback(() => { - if (activeTooltips.size === 0) { - return null; - } - - const sortedTooltips = Array.from(activeTooltips) - .map((name) => ({ - name, - priority: TOOLTIPS[name]?.priority ?? 0, - })) - .sort((a, b) => b.priority - a.priority); - - const highestPriorityTooltip = sortedTooltips.at(0); - - if (!highestPriorityTooltip) { - return null; - } - - return highestPriorityTooltip.name; - }, [activeTooltips]); - - const shouldTooltipBeVisible = useCallback( - (tooltipName: ProductTrainingTooltipName) => { - if (isLoadingOnyxValue(isOnboardingCompletedMetadata)) { - return false; - } - - const isDismissed = !!dismissedProductTraining?.[tooltipName]; - - if (isDismissed) { - return false; - } - const tooltipConfig = TOOLTIPS[tooltipName]; - - // if hasBeenAddedToNudgeMigration is true, and welcome modal is not dismissed, don't show tooltip - if (hasBeenAddedToNudgeMigration && !dismissedProductTraining?.[CONST.MIGRATED_USER_WELCOME_MODAL]) { - return false; - } - if (isOnboardingCompleted === false) { - return false; - } - - return tooltipConfig.shouldShow({ - shouldUseNarrowLayout, - }); - }, - [dismissedProductTraining, hasBeenAddedToNudgeMigration, isOnboardingCompleted, isOnboardingCompletedMetadata, shouldUseNarrowLayout], - ); - - const registerTooltip = useCallback( - (tooltipName: ProductTrainingTooltipName) => { - const shouldRegister = shouldTooltipBeVisible(tooltipName); - if (!shouldRegister) { - return; - } - setActiveTooltips((prev) => new Set([...prev, tooltipName])); - }, - [shouldTooltipBeVisible], - ); - - const shouldRenderTooltip = useCallback( - (tooltipName: ProductTrainingTooltipName) => { - // First check base conditions - const shouldShow = shouldTooltipBeVisible(tooltipName); - if (!shouldShow) { - return false; - } - const visibleTooltip = determineVisibleTooltip(); - - // If this is the highest priority visible tooltip, show it - if (tooltipName === visibleTooltip) { - return true; - } - - return false; - }, - [shouldTooltipBeVisible, determineVisibleTooltip], - ); - - const contextValue = useMemo( - () => ({ - shouldRenderTooltip, - registerTooltip, - unregisterTooltip, - }), - [shouldRenderTooltip, registerTooltip, unregisterTooltip], - ); - - return {children}; -} - -const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shouldShow = true) => { - const context = useContext(ProductTrainingContext); - const styles = useThemeStyles(); - const theme = useTheme(); - const {translate} = useLocalize(); - - if (!context) { - throw new Error('useProductTourContext must be used within a ProductTourProvider'); - } - - const {shouldRenderTooltip, registerTooltip, unregisterTooltip} = context; - - useEffect(() => { - if (shouldShow) { - registerTooltip(tooltipName); - return () => { - unregisterTooltip(tooltipName); - }; - } - return () => {}; - }, [tooltipName, registerTooltip, unregisterTooltip, shouldShow]); - - const renderProductTrainingTooltip = useCallback(() => { - const tooltip = TOOLTIPS[tooltipName]; - return ( - - - - {tooltip.content.map(({text, isBold}) => { - const translatedText = translate(text); - return ( - - {translatedText} - - ); - })} - - - ); - }, [ - styles.alignItemsCenter, - styles.flexRow, - styles.flexWrap, - styles.gap3, - styles.justifyContentCenter, - styles.mw100, - styles.p2, - styles.productTrainingTooltipText, - styles.textAlignCenter, - styles.textBold, - styles.textWrap, - theme.tooltipHighlightText, - tooltipName, - translate, - ]); - - const shouldShowProductTrainingTooltip = useMemo(() => { - return shouldRenderTooltip(tooltipName); - }, [shouldRenderTooltip, tooltipName]); - - const hideProductTrainingTooltip = useCallback(() => { - const tooltip = TOOLTIPS[tooltipName]; - tooltip.onHideTooltip(); - unregisterTooltip(tooltipName); - }, [tooltipName, unregisterTooltip]); - - return { - renderProductTrainingTooltip, - hideProductTrainingTooltip, - shouldShowProductTrainingTooltip, - }; -}; - -export {ProductTrainingContextProvider, useProductTrainingContext}; diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 21a5832052c0..a78845f126d2 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -1,4 +1,3 @@ -import {useIsFocused} from '@react-navigation/native'; import React, {useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -9,8 +8,6 @@ import ConfirmModal from '@components/ConfirmModal'; import DecisionModal from '@components/DecisionModal'; import * as Expensicons from '@components/Icon/Expensicons'; import {usePersonalDetails} from '@components/OnyxProvider'; -import {useProductTrainingContext} from '@components/ProductTrainingContext'; -import EducationalTooltip from '@components/Tooltip/EducationalTooltip'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -58,11 +55,6 @@ function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { const [isDeleteExpensesConfirmModalVisible, setIsDeleteExpensesConfirmModalVisible] = useState(false); const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); const [isDownloadErrorModalVisible, setIsDownloadErrorModalVisible] = useState(false); - const isFocused = useIsFocused(); - const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext( - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SEARCH_FILTER_BUTTON_TOOLTIP, - isFocused, - ); const {status, hash} = queryJSON; @@ -356,25 +348,12 @@ function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { shouldUseStyleUtilityForAnchorPosition /> ) : ( - -