loading.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { FC, useEffect, useState } from 'react'
  2. import LoadingBranded from '../../../shared/components/loading-branded'
  3. import i18n from '../../../i18n'
  4. import { useConnectionContext } from '../context/connection-context'
  5. import getMeta from '@/utils/meta'
  6. type LoadStatus = 'initial' | 'rendered' | 'connected' | 'loaded'
  7. const loadProgressPercentage: Record<LoadStatus, number> = {
  8. initial: 20,
  9. rendered: 40,
  10. connected: 70,
  11. loaded: 100,
  12. }
  13. // Pass in loading text from the server because i18n will not be ready initially
  14. export const Loading: FC<{ loadingText: string }> = ({
  15. loadingText,
  16. children,
  17. }) => {
  18. const [loadStatus, setLoadStatus] = useState<LoadStatus>('initial')
  19. const { connectionState, isConnected } = useConnectionContext()
  20. const loadProgress = loadProgressPercentage[loadStatus]
  21. const editorLoaded = loadStatus === 'loaded'
  22. const [i18nLoaded, setI18nLoaded] = useState(false)
  23. const [translationLoadError, setTranslationLoadError] = useState(false)
  24. // Advance to 40% once this component is rendered
  25. useEffect(() => {
  26. // Force a reflow now so that the animation from 20% to 40% occurs
  27. // eslint-disable-next-line no-void
  28. void document.body.offsetHeight
  29. setLoadStatus('rendered')
  30. }, [])
  31. useEffect(() => {
  32. i18n
  33. .then(() => setI18nLoaded(true))
  34. .catch(() => {
  35. setTranslationLoadError(true)
  36. })
  37. }, [])
  38. useEffect(() => {
  39. if (editorLoaded) {
  40. return
  41. }
  42. if (isConnected) {
  43. setLoadStatus(i18nLoaded ? 'loaded' : 'connected')
  44. }
  45. }, [i18nLoaded, editorLoaded, setLoadStatus, isConnected])
  46. const translationLoadErrorMessage = translationLoadError
  47. ? getMeta('ol-translationLoadErrorMessage')
  48. : ''
  49. return editorLoaded ? (
  50. <>{children}</>
  51. ) : (
  52. <div className="loading-screen">
  53. <LoadingBranded
  54. loadProgress={loadProgress}
  55. label={loadingText}
  56. error={connectionState.error || translationLoadErrorMessage}
  57. />
  58. </div>
  59. )
  60. }