_app.page.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import type { ReactElement, ReactNode } from 'react';
  2. import React, { useEffect } from 'react';
  3. import type { Locale } from '@growi/core';
  4. import type { NextPage } from 'next';
  5. import { appWithTranslation } from 'next-i18next';
  6. import type { AppContext, AppProps } from 'next/app';
  7. import App from 'next/app';
  8. import { useRouter } from 'next/router';
  9. import { SWRConfig } from 'swr';
  10. import * as nextI18nConfig from '^/config/next-i18next.config';
  11. import { GlobalFonts } from '~/components/FontFamily/GlobalFonts';
  12. import type { CrowiRequest } from '~/interfaces/crowi-request';
  13. import {
  14. useAppTitle, useConfidential, useGrowiVersion, useSiteUrl, useIsDefaultLogo, useForcedColorScheme,
  15. } from '~/stores-universal/context';
  16. import { swrGlobalConfiguration } from '~/utils/swr-utils';
  17. import { getLocaleAtServerSide, type CommonProps } from './utils/commons';
  18. import '~/styles/prebuilt/vendor.css';
  19. import '~/styles/style-app.scss';
  20. import { registerTransformerForObjectId } from './utils/objectid-transformer';
  21. // eslint-disable-next-line @typescript-eslint/ban-types
  22. export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  23. getLayout?: (page: ReactElement) => ReactNode,
  24. }
  25. type GrowiAppProps = AppProps & {
  26. Component: NextPageWithLayout,
  27. userLocale: Locale,
  28. };
  29. // register custom serializer
  30. registerTransformerForObjectId();
  31. function GrowiApp({ Component, pageProps, userLocale }: GrowiAppProps): JSX.Element {
  32. const router = useRouter();
  33. useEffect(() => {
  34. const updateLangAttribute = () => {
  35. if (document.documentElement.getAttribute('lang') !== userLocale) {
  36. document.documentElement.setAttribute('lang', userLocale);
  37. }
  38. };
  39. router.events.on('routeChangeComplete', updateLangAttribute);
  40. return () => {
  41. router.events.off('routeChangeComplete', updateLangAttribute);
  42. };
  43. }, [router, userLocale]);
  44. useEffect(() => {
  45. import('bootstrap/dist/js/bootstrap');
  46. }, []);
  47. const commonPageProps = pageProps as CommonProps;
  48. useAppTitle(commonPageProps.appTitle);
  49. useSiteUrl(commonPageProps.siteUrl);
  50. useConfidential(commonPageProps.confidential);
  51. useGrowiVersion(commonPageProps.growiVersion);
  52. useIsDefaultLogo(commonPageProps.isDefaultLogo);
  53. useForcedColorScheme(commonPageProps.forcedColorScheme);
  54. // Use the layout defined at the page level, if available
  55. const getLayout = Component.getLayout ?? (page => page);
  56. return (
  57. <>
  58. <GlobalFonts />
  59. <SWRConfig value={swrGlobalConfiguration}>
  60. {getLayout(<Component {...pageProps} />)}
  61. </SWRConfig>
  62. </>
  63. );
  64. }
  65. GrowiApp.getInitialProps = async(appContext: AppContext) => {
  66. const appProps = App.getInitialProps(appContext);
  67. const userLocale = getLocaleAtServerSide(appContext.ctx.req as unknown as CrowiRequest);
  68. return { ...appProps, userLocale };
  69. };
  70. export default appWithTranslation(GrowiApp, nextI18nConfig);