import type { ReactNode, JSX } from 'react'; import React, { useEffect } from 'react'; import type { Locale } from '@growi/core/dist/interfaces'; import { Provider } from 'jotai'; import type { NextPage } from 'next'; import { appWithTranslation } from 'next-i18next'; import type { AppContext, AppProps } from 'next/app'; import App from 'next/app'; import { useRouter } from 'next/router'; import { SWRConfig } from 'swr'; import * as nextI18nConfig from '^/config/next-i18next.config'; import { GlobalFonts } from '~/components/FontFamily/GlobalFonts'; import type { CrowiRequest } from '~/interfaces/crowi-request'; import { useHydrateGlobalEachAtoms, useHydrateGlobalInitialAtoms } from '~/states/global/hydrate'; import { swrGlobalConfiguration } from '~/utils/swr-utils'; import type { CommonEachProps, CommonInitialProps } from './common-props'; import { isCommonInitialProps } from './common-props'; import { getLocaleAtServerSide } from './utils/locale'; import { useNextjsRoutingPageRegister } from './utils/nextjs-routing-utils'; import { registerTransformerForObjectId } from './utils/objectid-transformer'; import '~/styles/prebuilt/vendor.css'; import '~/styles/style-app.scss'; // register custom serializer registerTransformerForObjectId(); const StateManagementContainer = ({ children }: { children: ReactNode }): JSX.Element => { return ( {children} ); }; // eslint-disable-next-line @typescript-eslint/ban-types export type NextPageWithLayout

= NextPage & { getLayout?: (page: JSX.Element) => ReactNode, } type CombinedCommonProps = CommonEachProps | (CommonEachProps & CommonInitialProps); type GrowiAppProps = AppProps & { Component: NextPageWithLayout, userLocale: Locale, }; const GrowiAppSubstance = ({ Component, pageProps, userLocale }: GrowiAppProps): JSX.Element => { const router = useRouter(); // Hydrate global atoms with server-side data useHydrateGlobalInitialAtoms(isCommonInitialProps(pageProps) ? pageProps : undefined); useHydrateGlobalEachAtoms(pageProps); useNextjsRoutingPageRegister(pageProps.nextjsRoutingPage); useEffect(() => { const updateLangAttribute = () => { if (document.documentElement.getAttribute('lang') !== userLocale) { document.documentElement.setAttribute('lang', userLocale); } }; router.events.on('routeChangeComplete', updateLangAttribute); return () => { router.events.off('routeChangeComplete', updateLangAttribute); }; }, [router, userLocale]); useEffect(() => { import('bootstrap/dist/js/bootstrap'); }, []); // Use the layout defined at the page level, if available const getLayout = Component.getLayout ?? (page => page); return <>{getLayout()}; }; function GrowiApp(props: GrowiAppProps): JSX.Element { return ( <> ); } // inject userLocale by context GrowiApp.getInitialProps = async(appContext: AppContext) => { const appProps = App.getInitialProps(appContext); const userLocale = getLocaleAtServerSide(appContext.ctx.req as unknown as CrowiRequest); return { ...appProps, userLocale }; }; export default appWithTranslation(GrowiApp, nextI18nConfig);