editor-switch-beginner-popover.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { ReactElement, useCallback, useEffect, useState } from 'react'
  2. import Close from '@/shared/components/close'
  3. import { useEditorContext } from '@/shared/context/editor-context'
  4. import useTutorial from '@/shared/hooks/promotions/use-tutorial'
  5. import { useUserContext } from '@/shared/context/user-context'
  6. import useScopeValue from '@/shared/hooks/use-scope-value'
  7. import { useTranslation } from 'react-i18next'
  8. import getMeta from '@/utils/meta'
  9. import OLPopover from '@/features/ui/components/ol/ol-popover'
  10. import OLOverlay from '@/features/ui/components/ol/ol-overlay'
  11. const CODE_EDITOR_POPOVER_TIMEOUT = 1000
  12. export const codeEditorModePrompt = 'code-editor-mode-prompt'
  13. export const EditorSwitchBeginnerPopover = ({
  14. children,
  15. targetRef,
  16. }: {
  17. children: ReactElement
  18. targetRef: React.RefObject<HTMLElement>
  19. }) => {
  20. const user = useUserContext()
  21. const { inactiveTutorials } = useEditorContext()
  22. const { t } = useTranslation()
  23. const [codeEditorOpened] = useScopeValue('editor.codeEditorOpened')
  24. const { completeTutorial } = useTutorial(codeEditorModePrompt, {
  25. location: 'logs',
  26. name: codeEditorModePrompt,
  27. })
  28. const [popoverShown, setPopoverShown] = useState(false)
  29. const shouldShowCodeEditorPopover = useCallback(() => {
  30. if (inactiveTutorials.includes(codeEditorModePrompt)) {
  31. return false
  32. }
  33. if (getMeta('ol-usedLatex') !== 'never') {
  34. // only show popover to the users that never used LaTeX (submitted in onboarding data collection)
  35. return false
  36. }
  37. if (codeEditorOpened) {
  38. // dont show popover if code editor was opened at some point
  39. return false
  40. }
  41. const msSinceSignedUp =
  42. user.signUpDate && Date.now() - new Date(user.signUpDate).getTime()
  43. if (msSinceSignedUp && msSinceSignedUp < 24 * 60 * 60 * 1000) {
  44. // dont show popover if user has signed up is less than 24 hours
  45. return false
  46. }
  47. return true
  48. }, [codeEditorOpened, inactiveTutorials, user.signUpDate])
  49. useEffect(() => {
  50. if (popoverShown && codeEditorOpened) {
  51. setPopoverShown(false)
  52. }
  53. }, [codeEditorOpened, popoverShown])
  54. useEffect(() => {
  55. const timeout = setTimeout(() => {
  56. if (shouldShowCodeEditorPopover()) {
  57. setPopoverShown(true)
  58. }
  59. }, CODE_EDITOR_POPOVER_TIMEOUT)
  60. return () => clearTimeout(timeout)
  61. }, [shouldShowCodeEditorPopover])
  62. return (
  63. <>
  64. {children}
  65. <OLOverlay
  66. placement="bottom"
  67. show={popoverShown}
  68. rootClose
  69. onHide={() => setPopoverShown(false)}
  70. target={targetRef.current}
  71. >
  72. <OLPopover id="editor-switch-popover">
  73. <div>
  74. <Close
  75. variant="dark"
  76. onDismiss={() => {
  77. setPopoverShown(false)
  78. completeTutorial({ event: 'promo-click', action: 'complete' })
  79. }}
  80. />
  81. <div className="tooltip-title">
  82. {t('code_editor_tooltip_title')}
  83. </div>
  84. <div>{t('code_editor_tooltip_message')}</div>
  85. </div>
  86. </OLPopover>
  87. </OLOverlay>
  88. </>
  89. )
  90. }