2022-08-17 17:38:21 +00:00
import { TooltipProvider } from "@radix-ui/react-tooltip" ;
2022-01-07 20:23:37 +00:00
import { SessionProvider } from "next-auth/react" ;
2022-07-28 19:58:26 +00:00
import { EventCollectionProvider } from "next-collect/client" ;
2023-02-16 22:39:57 +00:00
import type { SSRConfig } from "next-i18next" ;
import { appWithTranslation } from "next-i18next" ;
2022-07-28 19:58:26 +00:00
import { ThemeProvider } from "next-themes" ;
2022-05-17 19:31:49 +00:00
import type { AppProps as NextAppProps , AppProps as NextJsAppProps } from "next/app" ;
2023-02-16 22:39:57 +00:00
import type { NextRouter } from "next/router" ;
import type { ComponentProps , ReactNode } from "react" ;
2021-08-27 12:11:24 +00:00
2022-07-28 19:58:26 +00:00
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic" ;
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic" ;
2022-11-10 23:40:01 +00:00
import { trpc } from "@calcom/trpc/react" ;
2022-11-23 02:55:25 +00:00
import { MetaProvider } from "@calcom/ui" ;
2021-09-24 20:02:03 +00:00
2022-02-16 15:26:48 +00:00
import usePublicPage from "@lib/hooks/usePublicPage" ;
2023-02-16 22:39:57 +00:00
import type { WithNonceProps } from "@lib/withNonce" ;
2021-09-22 19:52:38 +00:00
2022-11-05 18:00:10 +00:00
const I18nextAdapter = appWithTranslation < NextJsAppProps < SSRConfig > & { children : React.ReactNode } > (
( { children } ) = > < > { children } < / >
) ;
2021-10-14 10:57:49 +00:00
2021-10-20 16:00:11 +00:00
// Workaround for https://github.com/vercel/next.js/issues/8592
2023-02-06 22:50:08 +00:00
export type AppProps = Omit < NextAppProps < WithNonceProps & Record < string , unknown > > , "Component" > & {
2022-07-28 10:50:25 +00:00
Component : NextAppProps [ "Component" ] & {
requiresLicense? : boolean ;
isThemeSupported? : boolean | ( ( arg : { router : NextRouter } ) = > boolean ) ;
2022-09-02 19:00:41 +00:00
getLayout ? : ( page : React.ReactElement , router : NextRouter ) = > ReactNode ;
2022-07-28 10:50:25 +00:00
} ;
2023-02-06 22:50:08 +00:00
2021-10-20 16:00:11 +00:00
/** Will be defined only is there was an error */
err? : Error ;
} ;
type AppPropsWithChildren = AppProps & {
children : ReactNode ;
} ;
const CustomI18nextProvider = ( props : AppPropsWithChildren ) = > {
2022-07-18 18:59:51 +00:00
/ * *
* i18n should never be clubbed with other queries , so that it ' s caching can be managed independently .
* We intend to not cache i18n query
* * /
2022-11-10 23:40:01 +00:00
const { i18n , locale } = trpc . viewer . public . i18n . useQuery ( undefined , {
trpc : { context : { skipBatch : true } } ,
} ) . data ? ? {
2021-11-03 14:02:17 +00:00
locale : "en" ,
} ;
2021-10-20 16:00:11 +00:00
2021-10-14 10:57:49 +00:00
const passedProps = {
. . . props ,
2021-10-20 16:00:11 +00:00
pageProps : {
. . . props . pageProps ,
. . . i18n ,
} ,
router : locale ? { locale } : props . router ,
2021-10-14 10:57:49 +00:00
} as unknown as ComponentProps < typeof I18nextAdapter > ;
return < I18nextAdapter { ...passedProps } / > ;
} ;
2021-10-20 16:00:11 +00:00
const AppProviders = ( props : AppPropsWithChildren ) = > {
2022-11-10 23:40:01 +00:00
const session = trpc . viewer . public . session . useQuery ( ) . data ;
2022-02-16 15:26:48 +00:00
// No need to have intercom on public pages - Good for Page Performance
const isPublicPage = usePublicPage ( ) ;
2022-07-28 19:58:26 +00:00
const isThemeSupported =
typeof props . Component . isThemeSupported === "function"
? props . Component . isThemeSupported ( { router : props.router } )
: props . Component . isThemeSupported ;
const forcedTheme = isThemeSupported ? undefined : "light" ;
// Use namespace of embed to ensure same namespaced embed are displayed with same theme. This allows different embeds on the same website to be themed differently
// One such example is our Embeds Demo and Testing page at http://localhost:3100
// Having `getEmbedNamespace` defined on window before react initializes the app, ensures that embedNamespace is available on the first mount and can be used as part of storageKey
const embedNamespace = typeof window !== "undefined" ? window . getEmbedNamespace ( ) : null ;
const storageKey = typeof embedNamespace === "string" ? ` embed-theme- ${ embedNamespace } ` : "theme" ;
2022-02-16 15:26:48 +00:00
const RemainingProviders = (
2022-07-28 19:58:26 +00:00
< EventCollectionProvider options = { { apiPath : "/api/collect-events" } } >
2022-09-02 23:55:12 +00:00
< SessionProvider session = { session || undefined } >
< CustomI18nextProvider { ...props } >
< TooltipProvider >
{ /* color-scheme makes background:transparent not work which is required by embed. We need to ensure next-theme adds color-scheme to `body` instead of `html`(https://github.com/pacocoursey/next-themes/blob/main/src/index.tsx#L74). Once that's done we can enable color-scheme support */ }
< ThemeProvider
2023-02-06 22:50:08 +00:00
nonce = { props . pageProps . nonce }
2022-09-02 23:55:12 +00:00
enableColorScheme = { false }
storageKey = { storageKey }
forcedTheme = { forcedTheme }
attribute = "class" >
< MetaProvider > { props . children } < / MetaProvider >
< / ThemeProvider >
< / TooltipProvider >
< / CustomI18nextProvider >
< / SessionProvider >
2022-07-28 19:58:26 +00:00
< / EventCollectionProvider >
2022-02-16 15:26:48 +00:00
) ;
2022-06-02 16:19:01 +00:00
if ( isPublicPage ) {
return RemainingProviders ;
}
2021-08-27 12:11:24 +00:00
return (
2022-06-02 16:19:01 +00:00
< DynamicHelpscoutProvider >
< DynamicIntercomProvider > { RemainingProviders } < / DynamicIntercomProvider >
< / DynamicHelpscoutProvider >
2021-08-27 12:11:24 +00:00
) ;
} ;
2021-09-30 12:28:30 +00:00
export default AppProviders ;