loading.tsx 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { FC, useEffect, useState } from 'react'
  2. import LoadingBranded from '@/shared/components/loading-branded'
  3. import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n'
  4. import getMeta from '@/utils/meta'
  5. import { useConnectionContext } from '../context/connection-context'
  6. import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
  7. import { LoadingError } from './loading-error'
  8. type Part = 'initial' | 'render' | 'connection' | 'translations' | 'project'
  9. const initialParts = new Set<Part>(['initial'])
  10. const totalParts = new Set<Part>([
  11. 'initial',
  12. 'render',
  13. 'connection',
  14. 'translations',
  15. 'project',
  16. ])
  17. export const Loading: FC<{
  18. setLoaded: (value: boolean) => void
  19. }> = ({ setLoaded }) => {
  20. const [loadedParts, setLoadedParts] = useState(initialParts)
  21. const progress = (loadedParts.size / totalParts.size) * 100
  22. useEffect(() => {
  23. setLoaded(progress === 100)
  24. }, [progress, setLoaded])
  25. const { connectionState, isConnected } = useConnectionContext()
  26. const i18n = useWaitForI18n()
  27. const { projectJoined } = useIdeReactContext()
  28. useEffect(() => {
  29. setLoadedParts(value => new Set(value).add('render'))
  30. }, [])
  31. useEffect(() => {
  32. if (isConnected) {
  33. setLoadedParts(value => new Set(value).add('connection'))
  34. }
  35. }, [isConnected])
  36. useEffect(() => {
  37. if (i18n.isReady) {
  38. setLoadedParts(value => new Set(value).add('translations'))
  39. }
  40. }, [i18n.isReady])
  41. useEffect(() => {
  42. if (projectJoined) {
  43. setLoadedParts(value => new Set(value).add('project'))
  44. }
  45. }, [projectJoined])
  46. // Use loading text from the server, because i18n will not be ready initially
  47. const label = getMeta('ol-loadingText')
  48. const hasError = Boolean(connectionState.error || i18n.error)
  49. return (
  50. <div className="loading-screen">
  51. <LoadingBranded
  52. loadProgress={progress}
  53. label={label}
  54. hasError={hasError}
  55. />
  56. {hasError && (
  57. <p className="loading-screen-error">
  58. <LoadingError
  59. connectionStateError={connectionState.error}
  60. i18nError={i18n.error}
  61. />
  62. </p>
  63. )}
  64. </div>
  65. )
  66. }