From e3db81d652f93ac3a0fec4142e5fb83c581ba4ce Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 22 Jul 2022 17:01:26 -0500 Subject: [PATCH] SoapboxMount: break SoapboxLoad into a separate component --- app/soapbox/containers/soapbox.tsx | 145 ++++++++++++++++------------- app/soapbox/hooks/index.ts | 1 + app/soapbox/hooks/useLocale.ts | 16 ++++ 3 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 app/soapbox/hooks/useLocale.ts diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index 29cfd74fb..26bd02488 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -25,7 +25,16 @@ import { 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 { + useAppSelector, + useAppDispatch, + useOwnAccount, + useFeatures, + useSoapboxConfig, + useSettings, + useSystemTheme, + useLocale, +} from 'soapbox/hooks'; import MESSAGES from 'soapbox/locales/messages'; import { useCachedLocationHandler } from 'soapbox/utils/redirect'; import { generateThemeCss } from 'soapbox/utils/theme'; @@ -36,9 +45,6 @@ import ErrorBoundary from '../components/error_boundary'; import UI from '../features/ui'; import { store } from '../store'; -/** Ensure the given locale exists in our codebase */ -const validLocale = (locale: string): boolean => Object.keys(MESSAGES).includes(locale); - // Configure global functions for developers createGlobals(store); @@ -72,27 +78,19 @@ const loadInitial = () => { /** Highest level node with the Redux store. */ const SoapboxMount = () => { useCachedLocationHandler(); - const dispatch = useAppDispatch(); - const me = useAppSelector(state => state.me); const instance = useAppSelector(state => state.instance); const account = useOwnAccount(); const settings = useSettings(); const soapboxConfig = useSoapboxConfig(); const features = useFeatures(); - const swUpdating = useAppSelector(state => state.meta.swUpdating); - - const locale = validLocale(settings.get('locale')) ? settings.get('locale') : 'en'; + const locale = useLocale(); 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>({}); - const [localeLoading, setLocaleLoading] = useState(true); - const [isLoaded, setIsLoaded] = useState(false); - const systemTheme = useSystemTheme(); const userTheme = settings.get('themeMode'); const darkMode = userTheme === 'dark' || (userTheme === 'system' && systemTheme === 'dark'); @@ -100,37 +98,11 @@ const SoapboxMount = () => { const themeCss = generateThemeCss(soapboxConfig); - // Load the user's locale - useEffect(() => { - MESSAGES[locale]().then(messages => { - setMessages(messages); - setLocaleLoading(false); - }).catch(() => { }); - }, [locale]); - - // Load initial data from the API - useEffect(() => { - dispatch(loadInitial()).then(() => { - setIsLoaded(true); - }).catch(() => { - setIsLoaded(true); - }); - }, []); - // @ts-ignore: I don't actually know what these should be, lol const shouldUpdateScroll = (prevRouterProps, { location }) => { return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prevRouterProps?.location?.state?.soapboxModalKey); }; - /** Whether to display a loading indicator. */ - const showLoading = [ - me === null, - me && !account, - !isLoaded, - localeLoading, - swUpdating, - ].some(Boolean); - const bodyClass = classNames('bg-white dark:bg-slate-900 text-base h-full', { 'no-reduce-motion': !settings.get('reduceMotion'), 'underline-links': settings.get('underlineLinks'), @@ -214,37 +186,80 @@ const SoapboxMount = () => { } }; + return ( + + + + <> + {helmet} + {renderBody()} + + + {(Component) => } + + + + {Component => } + + + + + + ); +}; + +interface ISoapboxLoad { + children: React.ReactNode, +} + +/** Initial data loader. */ +const SoapboxLoad: React.FC = ({ children }) => { + const dispatch = useAppDispatch(); + + const me = useAppSelector(state => state.me); + const account = useOwnAccount(); + const swUpdating = useAppSelector(state => state.meta.swUpdating); + const locale = useLocale(); + + const [messages, setMessages] = useState>({}); + const [localeLoading, setLocaleLoading] = useState(true); + const [isLoaded, setIsLoaded] = useState(false); + + /** Whether to display a loading indicator. */ + const showLoading = [ + me === null, + me && !account, + !isLoaded, + localeLoading, + swUpdating, + ].some(Boolean); + + // Load the user's locale + useEffect(() => { + MESSAGES[locale]().then(messages => { + setMessages(messages); + setLocaleLoading(false); + }).catch(() => { }); + }, [locale]); + + // Load initial data from the API + useEffect(() => { + dispatch(loadInitial()).then(() => { + setIsLoaded(true); + }).catch(() => { + setIsLoaded(true); + }); + }, []); + // intl is part of loading. // It's important nothing in here depends on intl. if (showLoading) { - return ( - <> - {helmet} - - - ); + return ; } return ( - {helmet} - - - - <> - {renderBody()} - - - {(Component) => } - - - - {Component => } - - - - - + {children} ); }; @@ -253,7 +268,9 @@ const SoapboxMount = () => { const Soapbox = () => { return ( - + + + ); }; diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 2cd767c2d..a2489d6ef 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -3,6 +3,7 @@ export { useAppDispatch } from './useAppDispatch'; export { useAppSelector } from './useAppSelector'; export { useDimensions } from './useDimensions'; export { useFeatures } from './useFeatures'; +export { useLocale } from './useLocale'; export { useOnScreen } from './useOnScreen'; export { useOwnAccount } from './useOwnAccount'; export { useRefEventHandler } from './useRefEventHandler'; diff --git a/app/soapbox/hooks/useLocale.ts b/app/soapbox/hooks/useLocale.ts new file mode 100644 index 000000000..1be278002 --- /dev/null +++ b/app/soapbox/hooks/useLocale.ts @@ -0,0 +1,16 @@ +import MESSAGES from 'soapbox/locales/messages'; + +import { useSettings } from './useSettings'; + +/** Ensure the given locale exists in our codebase */ +const validLocale = (locale: string): boolean => Object.keys(MESSAGES).includes(locale); + +/** Get valid locale from settings. */ +const useLocale = (fallback = 'en') => { + const settings = useSettings(); + const locale = settings.get('locale'); + + return validLocale(locale) ? locale : fallback; +}; + +export { useLocale };