diff --git a/app/soapbox/components/loading-screen.tsx b/app/soapbox/components/loading-screen.tsx new file mode 100644 index 0000000000..92882f98f8 --- /dev/null +++ b/app/soapbox/components/loading-screen.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +import LandingGradient from 'soapbox/components/landing-gradient'; +import { Spinner } from 'soapbox/components/ui'; + +/** Fullscreen loading indicator. */ +const LoadingScreen: React.FC = () => { + return ( +
+ + +
+ +
+
+ ); +}; + +export default LoadingScreen; diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index d8ffd97d54..fbb62d6e33 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -14,13 +14,16 @@ import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox'; import { fetchVerificationConfig } from 'soapbox/actions/verification'; import * as BuildConfig from 'soapbox/build_config'; import Helmet from 'soapbox/components/helmet'; -import { Spinner } from 'soapbox/components/ui'; +import LoadingScreen from 'soapbox/components/loading-screen'; import AuthLayout from 'soapbox/features/auth_layout'; -import OnboardingWizard from 'soapbox/features/onboarding/onboarding-wizard'; import PublicLayout from 'soapbox/features/public_layout'; -import NotificationsContainer from 'soapbox/features/ui/containers/notifications_container'; -import { ModalContainer } from 'soapbox/features/ui/util/async-components'; -import WaitlistPage from 'soapbox/features/verification/waitlist_page'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { + ModalContainer, + NotificationsContainer, + OnboardingWizard, + WaitlistPage, +} from 'soapbox/features/ui/util/async-components'; import { createGlobals } from 'soapbox/globals'; import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures, useSoapboxConfig, useSettings, useSystemTheme } from 'soapbox/hooks'; import MESSAGES from 'soapbox/locales/messages'; @@ -31,7 +34,6 @@ import { checkOnboardingStatus } from '../actions/onboarding'; import { preload } from '../actions/preload'; import ErrorBoundary from '../components/error_boundary'; import UI from '../features/ui'; -import BundleContainer from '../features/ui/containers/bundle_container'; import { store } from '../store'; /** Ensure the given locale exists in our codebase */ @@ -67,6 +69,7 @@ const loadInitial = () => { }; }; +/** Highest level node with the Redux store. */ const SoapboxMount = () => { useCachedLocationHandler(); const dispatch = useAppDispatch(); @@ -80,7 +83,9 @@ const SoapboxMount = () => { const locale = validLocale(settings.get('locale')) ? settings.get('locale') : 'en'; + const waitlisted = account && !account.source.get('approved', true); const needsOnboarding = useAppSelector(state => state.onboarding.needsOnboarding); + const showOnboarding = account && !waitlisted && needsOnboarding; const singleUserMode = soapboxConfig.singleUserMode && soapboxConfig.singleUserModeProfile; const [messages, setMessages] = useState>({}); @@ -124,20 +129,6 @@ const SoapboxMount = () => { localeLoading, ].some(Boolean); - if (showLoading) { - return ( -
- - {themeCss && } - - - -
- ); - } - - const waitlisted = account && !account.source.get('approved', true); - const bodyClass = classNames('bg-white dark:bg-slate-900 text-base h-full', { 'no-reduce-motion': !settings.get('reduceMotion'), 'underline-links': settings.get('underlineLinks'), @@ -145,94 +136,117 @@ const SoapboxMount = () => { 'demetricator': settings.get('demetricator'), }); - if (account && !waitlisted && needsOnboarding) { - return ( - - - - - {themeCss && } - - + const helmet = ( + + + + {themeCss && } + + + ); - - - - - - - + /** Render the onboarding flow. */ + const renderOnboarding = () => ( + + {(Component) => } + + ); + + /** Render the auth layout or UI. */ + const renderSwitch = () => ( + + + + {/* Redirect signup route depending on Pepe enablement. */} + {/* We should prefer using /signup in components. */} + {pepeEnabled ? ( + + ) : ( + + )} + + {waitlisted && ( + ( + + {(Component) => } + + )} + /> + )} + + {!me && (singleUserMode + ? + : )} + + {!me && ( + + )} + + + + + + {(features.accountCreation && instance.registrations) && ( + + )} + + {pepeEnabled && ( + + )} + + + + + + + + ); + + /** Render the onboarding flow or UI. */ + const renderBody = () => { + if (showOnboarding) { + return renderOnboarding(); + } else { + return renderSwitch(); + } + }; + + // intl is part of loading. + // It's important nothing in here depends on intl. + if (showLoading) { + return ( + <> + {helmet} + + ); } return ( - - - - {themeCss && } - - - + {helmet} - <> - - - + + <> + {renderBody()} - {/* Redirect signup route depending on Pepe enablement. */} - {/* We should prefer using /signup in components. */} - {pepeEnabled ? ( - - ) : ( - - )} + + {(Component) => } + - {waitlisted && ( - <> - } /> - - - {Component => } - - - )} - - {!me && (singleUserMode - ? - : )} - - {!me && ( - - )} - - - - - - {(features.accountCreation && instance.registrations) && ( - - )} - - {pepeEnabled && ( - - )} - - - - - - - - - + + {Component => } + + + ); }; +/** The root React node of the application. */ const Soapbox = () => { return ( diff --git a/app/soapbox/features/auth_layout/index.tsx b/app/soapbox/features/auth_layout/index.tsx index 1ac59b3de8..ca72f41073 100644 --- a/app/soapbox/features/auth_layout/index.tsx +++ b/app/soapbox/features/auth_layout/index.tsx @@ -4,8 +4,6 @@ import { Link, Redirect, Route, Switch, useHistory } from 'react-router-dom'; import LandingGradient from 'soapbox/components/landing-gradient'; import SiteLogo from 'soapbox/components/site-logo'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { NotificationsContainer } from 'soapbox/features/ui/util/async-components'; import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks'; import { Button, Card, CardBody } from '../../components/ui'; @@ -86,10 +84,6 @@ const AuthLayout = () => { - - - {(Component) => } - ); }; diff --git a/app/soapbox/features/public_layout/index.tsx b/app/soapbox/features/public_layout/index.tsx index 3fe4834a5e..5c7e451077 100644 --- a/app/soapbox/features/public_layout/index.tsx +++ b/app/soapbox/features/public_layout/index.tsx @@ -2,11 +2,6 @@ import React from 'react'; import { Switch, Route, Redirect } from 'react-router-dom'; import LandingGradient from 'soapbox/components/landing-gradient'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { - NotificationsContainer, - ModalContainer, -} from 'soapbox/features/ui/util/async-components'; import { useAppSelector } from 'soapbox/hooks'; import { isStandalone } from 'soapbox/utils/state'; @@ -42,14 +37,6 @@ const PublicLayout = () => {