loading.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. type Part = 'initial' | 'render' | 'connection' | 'translations' | 'project'
  8. const initialParts = new Set<Part>(['initial'])
  9. const totalParts = new Set<Part>([
  10. 'initial',
  11. 'render',
  12. 'connection',
  13. 'translations',
  14. 'project',
  15. ])
  16. export const Loading: FC<{
  17. setLoaded: (value: boolean) => void
  18. }> = ({ setLoaded }) => {
  19. const [loadedParts, setLoadedParts] = useState(initialParts)
  20. const progress = (loadedParts.size / totalParts.size) * 100
  21. useEffect(() => {
  22. setLoaded(progress === 100)
  23. }, [progress, setLoaded])
  24. const { connectionState, isConnected } = useConnectionContext()
  25. const i18n = useWaitForI18n()
  26. const { projectJoined } = useIdeReactContext()
  27. useEffect(() => {
  28. setLoadedParts(value => new Set(value).add('render'))
  29. }, [])
  30. useEffect(() => {
  31. if (isConnected) {
  32. setLoadedParts(value => new Set(value).add('connection'))
  33. }
  34. }, [isConnected])
  35. useEffect(() => {
  36. if (i18n.isReady) {
  37. setLoadedParts(value => new Set(value).add('translations'))
  38. }
  39. }, [i18n.isReady])
  40. useEffect(() => {
  41. if (projectJoined) {
  42. setLoadedParts(value => new Set(value).add('project'))
  43. }
  44. }, [projectJoined])
  45. const getLoadingScreenError = (): string => {
  46. if (connectionState.error) {
  47. // NOTE: translations not ready yet
  48. return connectionState.error === 'io-not-loaded'
  49. ? 'Could not connect to websocket server :('
  50. : connectionState.error
  51. }
  52. if (i18n.error) {
  53. return getMeta('ol-translationLoadErrorMessage')
  54. }
  55. return ''
  56. }
  57. // Use loading text from the server, because i18n will not be ready initially
  58. const label = getMeta('ol-loadingText')
  59. const hasError = Boolean(connectionState.error || i18n.error)
  60. return (
  61. <div className="loading-screen">
  62. <LoadingBranded
  63. loadProgress={progress}
  64. label={label}
  65. hasError={hasError}
  66. />
  67. {hasError && (
  68. <p className="loading-screen-error">{getLoadingScreenError()}</p>
  69. )}
  70. </div>
  71. )
  72. }