unsaved-docs-alert.tsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { FC, useEffect, useMemo, useRef } from 'react'
  2. import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
  3. import { useTranslation } from 'react-i18next'
  4. import OLNotification from '@/shared/components/ol/ol-notification'
  5. import { sendMB } from '@/infrastructure/event-tracking'
  6. import { useConnectionContext } from '@/features/ide-react/context/connection-context'
  7. const MAX_UNSAVED_ALERT_SECONDS = 15
  8. export const UnsavedDocsAlert: FC<{ unsavedDocs: Map<string, number> }> = ({
  9. unsavedDocs,
  10. }) => (
  11. <>
  12. {[...unsavedDocs.entries()].map(
  13. ([docId, seconds]) =>
  14. seconds >= MAX_UNSAVED_ALERT_SECONDS && (
  15. <UnsavedDocAlert key={docId} docId={docId} seconds={seconds} />
  16. )
  17. )}
  18. </>
  19. )
  20. const UnsavedDocAlert: FC<{ docId: string; seconds: number }> = ({
  21. docId,
  22. seconds,
  23. }) => {
  24. const { pathInFolder, findEntityByPath } = useFileTreePathContext()
  25. const { socket } = useConnectionContext()
  26. const { t } = useTranslation()
  27. const recordedRef = useRef(false)
  28. useEffect(() => {
  29. if (!recordedRef.current) {
  30. recordedRef.current = true
  31. sendMB('unsaved-doc-alert-shown', {
  32. docId,
  33. transport: socket.socket.transport?.name,
  34. })
  35. }
  36. }, [docId, socket])
  37. const doc = useMemo(() => {
  38. const path = pathInFolder(docId)
  39. return path ? findEntityByPath(path) : null
  40. }, [docId, findEntityByPath, pathInFolder])
  41. if (!doc) {
  42. return null
  43. }
  44. return (
  45. <OLNotification
  46. type="warning"
  47. content={t('saving_notification_with_seconds', {
  48. docname: doc.entity.name,
  49. seconds,
  50. })}
  51. />
  52. )
  53. }