| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- 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 (
- <SWRConfig value={swrGlobalConfiguration}>
- <Provider>
- {children}
- </Provider>
- </SWRConfig>
- );
- };
- // eslint-disable-next-line @typescript-eslint/ban-types
- export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
- getLayout?: (page: JSX.Element) => ReactNode,
- }
- type CombinedCommonProps = CommonEachProps | (CommonEachProps & CommonInitialProps);
- type GrowiAppProps = AppProps<CombinedCommonProps> & {
- Component: NextPageWithLayout<CombinedCommonProps>,
- 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(<Component {...pageProps} />)}</>;
- };
- function GrowiApp(props: GrowiAppProps): JSX.Element {
- return (
- <>
- <GlobalFonts />
- <StateManagementContainer>
- <GrowiAppSubstance {...props} />
- </StateManagementContainer>
- </>
- );
- }
- // 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);
|