grammarly-warning.tsx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { useCallback, useEffect, useState } from 'react'
  2. import { Button } from 'react-bootstrap'
  3. import { Nullable } from '../../../../../types/utils'
  4. import customLocalStorage from '../../../infrastructure/local-storage'
  5. import useScopeValue from '../../../shared/hooks/use-scope-value'
  6. import grammarlyExtensionPresent from '../../../shared/utils/grammarly'
  7. type GrammarlyWarningProps = {
  8. delay: number
  9. }
  10. export default function GrammarlyWarning({ delay }: GrammarlyWarningProps) {
  11. const [show, setShow] = useState(false)
  12. const [newSourceEditor] = useScopeValue('editor.newSourceEditor')
  13. const [showRichText] = useScopeValue('editor.showRichText')
  14. const grammarly = grammarlyExtensionPresent()
  15. const hasDismissedGrammarlyWarning = customLocalStorage.getItem(
  16. 'editor.has_dismissed_grammarly_warning'
  17. )
  18. useEffect(() => {
  19. const showGrammarlyWarning =
  20. !hasDismissedGrammarlyWarning &&
  21. grammarly &&
  22. newSourceEditor &&
  23. !showRichText
  24. let timeoutID: Nullable<number>
  25. if (showGrammarlyWarning) {
  26. const timeout = window.setTimeout(() => {
  27. setShow(true)
  28. timeoutID = null
  29. }, delay)
  30. timeoutID = timeout
  31. }
  32. return () => {
  33. if (timeoutID) {
  34. clearTimeout(timeoutID)
  35. }
  36. }
  37. }, [
  38. grammarly,
  39. hasDismissedGrammarlyWarning,
  40. newSourceEditor,
  41. showRichText,
  42. delay,
  43. ])
  44. const handleClose = useCallback(() => {
  45. setShow(false)
  46. customLocalStorage.setItem('editor.has_dismissed_grammarly_warning', true)
  47. }, [])
  48. if (!show) {
  49. return null
  50. }
  51. return (
  52. <div className="alert alert-info grammarly-warning" role="alert">
  53. <Button
  54. className="close"
  55. data-dismiss="alert"
  56. aria-label="Close"
  57. onClick={handleClose}
  58. >
  59. <span aria-hidden="true">&times;</span>
  60. </Button>
  61. <div className="warning-content">
  62. A browser extension, for example Grammarly, may be slowing down
  63. Overleaf.{' '}
  64. <a
  65. className="warning-link"
  66. href="/learn/how-to/Use_Grammarly_with_Overleaf#Performance_issues"
  67. target="_blank"
  68. >
  69. Find out how to avoid this
  70. </a>
  71. </div>
  72. </div>
  73. )
  74. }