1
- import React , { memo , useEffect , useRef , useState } from 'react' ;
1
+ import React , { memo , useCallback , useEffect , useRef , useState } from 'react' ;
2
2
import type { LayoutRectangle , NativeSyntheticEvent } from 'react-native' ;
3
- import { useOnyx } from 'react-native-onyx' ;
4
3
import GenericTooltip from '@components/Tooltip/GenericTooltip' ;
5
4
import type { EducationalTooltipProps } from '@components/Tooltip/types' ;
5
+ import onyxSubscribe from '@libs/onyxSubscribe' ;
6
6
import ONYXKEYS from '@src/ONYXKEYS' ;
7
+ import type { Modal } from '@src/types/onyx' ;
7
8
import measureTooltipCoordinate from './measureTooltipCoordinate' ;
8
9
9
10
type LayoutChangeEventWithTarget = NativeSyntheticEvent < { layout : LayoutRectangle ; target : HTMLElement } > ;
@@ -12,14 +13,45 @@ type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle
12
13
* A component used to wrap an element intended for displaying a tooltip.
13
14
* This tooltip would show immediately without user's interaction and hide after 5 seconds.
14
15
*/
15
- function BaseEducationalTooltip ( { children, onHideTooltip, shouldAutoDismiss = false , ...props } : EducationalTooltipProps ) {
16
+ function BaseEducationalTooltip ( { children, onHideTooltip, shouldRender = false , shouldAutoDismiss = false , ...props } : EducationalTooltipProps ) {
16
17
const hideTooltipRef = useRef < ( ) => void > ( ) ;
17
18
18
19
const [ shouldMeasure , setShouldMeasure ] = useState ( false ) ;
19
20
const show = useRef < ( ) => void > ( ) ;
20
- const [ modal ] = useOnyx ( ONYXKEYS . MODAL ) ;
21
+ const [ modal , setModal ] = useState < Modal > ( {
22
+ willAlertModalBecomeVisible : false ,
23
+ isVisible : false ,
24
+ } ) ;
21
25
22
- const shouldShow = ! modal ?. willAlertModalBecomeVisible && ! modal ?. isVisible ;
26
+ const shouldShow = ! modal ?. willAlertModalBecomeVisible && ! modal ?. isVisible && shouldRender ;
27
+
28
+ useEffect ( ( ) => {
29
+ if ( ! shouldRender ) {
30
+ return ;
31
+ }
32
+ const unsubscribeOnyxModal = onyxSubscribe ( {
33
+ key : ONYXKEYS . MODAL ,
34
+ callback : ( modalArg ) => {
35
+ if ( modalArg === undefined ) {
36
+ return ;
37
+ }
38
+ setModal ( modalArg ) ;
39
+ } ,
40
+ } ) ;
41
+ return ( ) => {
42
+ unsubscribeOnyxModal ( ) ;
43
+ } ;
44
+ } , [ shouldRender ] ) ;
45
+
46
+ const didShow = useRef ( false ) ;
47
+
48
+ const closeTooltip = useCallback ( ( ) => {
49
+ if ( ! didShow . current ) {
50
+ return ;
51
+ }
52
+ hideTooltipRef . current ?.( ) ;
53
+ onHideTooltip ?.( ) ;
54
+ } , [ onHideTooltip ] ) ;
23
55
24
56
useEffect (
25
57
( ) => ( ) => {
@@ -34,36 +66,45 @@ function BaseEducationalTooltip({children, onHideTooltip, shouldAutoDismiss = fa
34
66
35
67
// Automatically hide tooltip after 5 seconds
36
68
useEffect ( ( ) => {
37
- if ( ! hideTooltipRef . current || ! shouldAutoDismiss ) {
69
+ if ( ! shouldAutoDismiss ) {
38
70
return ;
39
71
}
40
72
41
73
// If the modal is open, hide the tooltip immediately and clear the timeout
42
74
if ( ! shouldShow ) {
43
- hideTooltipRef . current ( ) ;
75
+ closeTooltip ( ) ;
44
76
return ;
45
77
}
46
78
47
79
// Automatically hide tooltip after 5 seconds if shouldAutoDismiss is true
48
80
const timerID = setTimeout ( ( ) => {
49
- hideTooltipRef . current ?.( ) ;
50
- onHideTooltip ?.( ) ;
81
+ closeTooltip ( ) ;
51
82
} , 5000 ) ;
52
83
return ( ) => {
53
84
clearTimeout ( timerID ) ;
54
85
} ;
55
- } , [ shouldAutoDismiss , shouldShow , onHideTooltip ] ) ;
86
+ } , [ shouldAutoDismiss , shouldShow , closeTooltip ] ) ;
56
87
57
88
useEffect ( ( ) => {
58
- if ( ! shouldMeasure || ! shouldShow ) {
89
+ if ( ! shouldMeasure || ! shouldShow || didShow . current ) {
59
90
return ;
60
91
}
61
92
// When tooltip is used inside an animated view (e.g. popover), we need to wait for the animation to finish before measuring content.
62
- setTimeout ( ( ) => {
93
+ const timerID = setTimeout ( ( ) => {
63
94
show . current ?.( ) ;
95
+ didShow . current = true ;
64
96
} , 500 ) ;
97
+ return ( ) => {
98
+ clearTimeout ( timerID ) ;
99
+ } ;
65
100
} , [ shouldMeasure , shouldShow ] ) ;
66
101
102
+ useEffect (
103
+ ( ) => closeTooltip ,
104
+ // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
105
+ [ ] ,
106
+ ) ;
107
+
67
108
return (
68
109
< GenericTooltip
69
110
shouldForceAnimate
0 commit comments