grammarly-warning.tsx 2.3 KB

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