diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index 322f28aa246d..dc71c6614c67 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -187,7 +187,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti shiftHorizontal={variables.gbrTooltipShiftHorizontal} shiftVertical={variables.composerTooltipShiftVertical} wrapperStyle={styles.quickActionTooltipWrapper} - onHideTooltip={() => User.dismissGBRTooltip()} + onHideTooltip={User.dismissGBRTooltip} > diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index ef5327feba31..a9481f3cf3b3 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -1,9 +1,10 @@ -import React, {memo, useEffect, useRef, useState} from 'react'; +import React, {memo, useCallback, useEffect, useRef, useState} from 'react'; import type {LayoutRectangle, NativeSyntheticEvent} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; import GenericTooltip from '@components/Tooltip/GenericTooltip'; import type {EducationalTooltipProps} from '@components/Tooltip/types'; +import onyxSubscribe from '@libs/onyxSubscribe'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Modal} from '@src/types/onyx'; import measureTooltipCoordinate from './measureTooltipCoordinate'; type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle; target: HTMLElement}>; @@ -12,14 +13,45 @@ type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle * A component used to wrap an element intended for displaying a tooltip. * This tooltip would show immediately without user's interaction and hide after 5 seconds. */ -function BaseEducationalTooltip({children, onHideTooltip, shouldAutoDismiss = false, ...props}: EducationalTooltipProps) { +function BaseEducationalTooltip({children, onHideTooltip, shouldRender = false, shouldAutoDismiss = false, ...props}: EducationalTooltipProps) { const hideTooltipRef = useRef<() => void>(); const [shouldMeasure, setShouldMeasure] = useState(false); const show = useRef<() => void>(); - const [modal] = useOnyx(ONYXKEYS.MODAL); + const [modal, setModal] = useState({ + willAlertModalBecomeVisible: false, + isVisible: false, + }); - const shouldShow = !modal?.willAlertModalBecomeVisible && !modal?.isVisible; + const shouldShow = !modal?.willAlertModalBecomeVisible && !modal?.isVisible && shouldRender; + + useEffect(() => { + if (!shouldRender) { + return; + } + const unsubscribeOnyxModal = onyxSubscribe({ + key: ONYXKEYS.MODAL, + callback: (modalArg) => { + if (modalArg === undefined) { + return; + } + setModal(modalArg); + }, + }); + return () => { + unsubscribeOnyxModal(); + }; + }, [shouldRender]); + + const didShow = useRef(false); + + const closeTooltip = useCallback(() => { + if (!didShow.current) { + return; + } + hideTooltipRef.current?.(); + onHideTooltip?.(); + }, [onHideTooltip]); useEffect( () => () => { @@ -34,36 +66,45 @@ function BaseEducationalTooltip({children, onHideTooltip, shouldAutoDismiss = fa // Automatically hide tooltip after 5 seconds useEffect(() => { - if (!hideTooltipRef.current || !shouldAutoDismiss) { + if (!shouldAutoDismiss) { return; } // If the modal is open, hide the tooltip immediately and clear the timeout if (!shouldShow) { - hideTooltipRef.current(); + closeTooltip(); return; } // Automatically hide tooltip after 5 seconds if shouldAutoDismiss is true const timerID = setTimeout(() => { - hideTooltipRef.current?.(); - onHideTooltip?.(); + closeTooltip(); }, 5000); return () => { clearTimeout(timerID); }; - }, [shouldAutoDismiss, shouldShow, onHideTooltip]); + }, [shouldAutoDismiss, shouldShow, closeTooltip]); useEffect(() => { - if (!shouldMeasure || !shouldShow) { + if (!shouldMeasure || !shouldShow || didShow.current) { return; } // When tooltip is used inside an animated view (e.g. popover), we need to wait for the animation to finish before measuring content. - setTimeout(() => { + const timerID = setTimeout(() => { show.current?.(); + didShow.current = true; }, 500); + return () => { + clearTimeout(timerID); + }; }, [shouldMeasure, shouldShow]); + useEffect( + () => closeTooltip, + // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps + [], + ); + return ( SearchActions.dismissSavedSearchRenameTooltip(), + onHideTooltip: SearchActions.dismissSavedSearchRenameTooltip, renderTooltipContent: () => { return ( diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index e4b0eef6ca52..48278e6631b9 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -407,7 +407,7 @@ function ReportActionCompose({ shouldRender={!shouldHideEducationalTooltip && shouldShowEducationalTooltip} renderTooltipContent={renderWorkspaceChatTooltip} shouldUseOverlay - onHideTooltip={() => User.dismissWorkspaceTooltip()} + onHideTooltip={User.dismissWorkspaceTooltip} anchorAlignment={{ horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM,