From 6174a6dd262d5f633f7c837d116d8e559eccad09 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:41:16 +0100 Subject: [PATCH 01/30] Make it possible to click the element the product training tooltip is pointing to --- src/components/FloatingActionButton.tsx | 3 +- .../LHNOptionsList/OptionRowLHN.tsx | 18 ++++---- src/components/MenuItem.tsx | 6 --- .../ProductTrainingContext/index.tsx | 15 ++++--- src/components/Search/SearchPageHeader.tsx | 19 ++++---- .../BaseEducationalTooltip.tsx | 43 +++---------------- .../EducationalTooltip/TooltipManager.ts | 30 ------------- src/components/Tooltip/GenericTooltip.tsx | 4 +- src/components/Tooltip/types.ts | 6 --- src/hooks/useBottomTabIsFocused.ts | 7 +++ .../Navigation/AppNavigator/AuthScreens.tsx | 2 - .../BottomTabBar.tsx | 3 +- src/libs/actions/Modal.ts | 3 -- src/pages/Search/SearchPage.tsx | 7 ++- src/pages/Search/SearchTypeMenuNarrow.tsx | 12 +++--- .../ReportActionCompose.tsx | 5 +-- src/pages/home/report/ReportFooter.tsx | 6 ++- 17 files changed, 64 insertions(+), 125 deletions(-) delete mode 100644 src/components/Tooltip/EducationalTooltip/TooltipManager.ts diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx index e0f0ff4e6dcd..f503fcc187e3 100644 --- a/src/components/FloatingActionButton.tsx +++ b/src/components/FloatingActionButton.tsx @@ -105,6 +105,7 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo ); const toggleFabAction = (event: GestureResponderEvent | KeyboardEvent | undefined) => { + hideProductTrainingTooltip(); // Drop focus to avoid blue focus ring. fabPressable.current?.blur(); onPress(event); @@ -117,11 +118,9 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo horizontal: isNarrowScreenOnWeb ? CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER : CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, }} - shouldUseOverlay shiftHorizontal={isNarrowScreenOnWeb ? 0 : variables.fabTooltipShiftHorizontal} renderTooltipContent={renderProductTrainingTooltip} wrapperStyle={styles.productTrainingTooltipWrapper} - onHideTooltip={hideProductTrainingTooltip} > { diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index efdd9659c845..368c89de83a5 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 {useFocusEffect, useIsFocused} from '@react-navigation/native'; +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'; @@ -44,6 +44,8 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti const StyleUtils = useStyleUtils(); const [isScreenFocused, setIsScreenFocused] = useState(false); const {shouldUseNarrowLayout} = useResponsiveLayout(); + const [modal] = useOnyx(ONYXKEYS.MODAL); + const isModalVisible = modal?.isVisible || modal?.willAlertModalBecomeVisible; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${optionItem?.reportID || -1}`); @@ -54,12 +56,11 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti 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; + const tooltipToRender = 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]); + const isFocusedHookResult = useIsFocused(); + + const shouldShowTooltip = shouldUseNarrowLayout ? isScreenFocused && !isModalVisible && isFocusedHookResult : !isModalVisible && isFocusedHookResult; const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext(tooltipToRender, shouldShowTooltip); const {translate} = useLocalize(); @@ -165,10 +166,8 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti horizontal: isActiveWorkspaceChat ? CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT : CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, }} - shouldUseOverlay shiftHorizontal={isActiveWorkspaceChat ? variables.workspaceLHNtooltipShiftHorizontal : variables.gbrTooltipShiftHorizontal} shiftVertical={isActiveWorkspaceChat ? 0 : variables.composerTooltipShiftVertical} - onHideTooltip={hideProductTrainingTooltip} wrapperStyle={styles.productTrainingTooltipWrapper} > @@ -183,6 +182,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti event?.preventDefault(); // Enable Composer to focus on clicking the same chat after opening the context menu. ReportActionComposeFocusManager.focus(); + hideProductTrainingTooltip(); onSelectRow(optionItem, popoverAnchor); }} onMouseDown={(event) => { diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 19703f7a3c92..1c6234031898 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -340,9 +340,6 @@ type MenuItemBaseProps = { /** Should selected item be marked with checkmark */ shouldShowSelectedItemCheck?: boolean; - /** Handles what to do when hiding the tooltip */ - onHideTooltip?: () => void; - /** Should use auto width for the icon container. */ shouldIconUseAutoWidthStyle?: boolean; @@ -458,7 +455,6 @@ function MenuItem( renderTooltipContent, additionalIconStyles, shouldShowSelectedItemCheck = false, - onHideTooltip, shouldIconUseAutoWidthStyle = false, shouldBreakWord = false, }: MenuItemProps, @@ -596,8 +592,6 @@ function MenuItem( wrapperStyle={tooltipWrapperStyle} shiftHorizontal={tooltipShiftHorizontal} shiftVertical={tooltipShiftVertical} - shouldAutoDismiss - onHideTooltip={onHideTooltip} > diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index 7cfcf4d3bfa7..f7abbfad6204 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -39,6 +39,9 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { const [activeTooltips, setActiveTooltips] = useState>(new Set()); + useEffect(() => { + console.log('activeTooltips', activeTooltips); + }, [activeTooltips]); const unregisterTooltip = useCallback( (tooltipName: ProductTrainingTooltipName) => { setActiveTooltips((prev) => { @@ -156,11 +159,10 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou useEffect(() => { if (shouldShow) { registerTooltip(tooltipName); - return () => { - unregisterTooltip(tooltipName); - }; } - return () => {}; + return () => { + unregisterTooltip(tooltipName); + }; }, [tooltipName, registerTooltip, unregisterTooltip, shouldShow]); const renderProductTrainingTooltip = useCallback(() => { @@ -209,10 +211,13 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou }, [shouldRenderTooltip, tooltipName]); const hideProductTrainingTooltip = useCallback(() => { + if (!shouldShowProductTrainingTooltip) { + return; + } const tooltip = TOOLTIPS[tooltipName]; tooltip.onHideTooltip(); unregisterTooltip(tooltipName); - }, [tooltipName, unregisterTooltip]); + }, [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip]); return { renderProductTrainingTooltip, diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 21a5832052c0..819c4ff7bad0 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -32,11 +32,11 @@ import {useSearchContext} from './SearchContext'; import SearchPageHeaderInput from './SearchPageHeaderInput'; import type {PaymentData, SearchQueryJSON} from './types'; -type SearchPageHeaderProps = {queryJSON: SearchQueryJSON}; +type SearchPageHeaderProps = {queryJSON: SearchQueryJSON; isFocused: boolean}; type SearchHeaderOptionValue = DeepValueOf | undefined; -function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { +function SearchPageHeader({queryJSON, isFocused}: SearchPageHeaderProps) { const {translate} = useLocalize(); const theme = useTheme(); const styles = useThemeStyles(); @@ -58,11 +58,8 @@ 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 [modal] = useOnyx(ONYXKEYS.MODAL); + const isModalVisible = modal?.isVisible || modal?.willAlertModalBecomeVisible; const {status, hash} = queryJSON; @@ -289,6 +286,11 @@ function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { lastPaymentMethods, ]); + const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext( + CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SEARCH_FILTER_BUTTON_TOOLTIP, + isFocused && !isModalVisible && !!queryJSON && headerButtonsOptions.length === 0, + ); + if (shouldUseNarrowLayout) { if (selectionMode?.isEnabled) { return ( @@ -334,6 +336,7 @@ function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { } const onFiltersButtonPress = () => { + hideProductTrainingTooltip(); const filterFormValues = SearchQueryUtils.buildFilterFormValuesFromQuery(queryJSON, policyCategories, policyTagsLists, currencyList, personalDetails, cardList, reports, taxRates); SearchActions.updateAdvancedFilters(filterFormValues); @@ -362,11 +365,9 @@ function SearchPageHeader({queryJSON}: SearchPageHeaderProps) { vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, }} - shouldUseOverlay shiftHorizontal={variables.searchFiltersTooltipShiftHorizontal} wrapperStyle={styles.productTrainingTooltipWrapper} renderTooltipContent={renderProductTrainingTooltip} - onHideTooltip={hideProductTrainingTooltip} >