diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 9b47a74e1..8ff4c6a9f 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -1,7 +1,5 @@ import { setupI18n } from "@/ui/i18n"; -import { CacheProvider } from "@emotion/react"; import { APPS, APP_TITLES } from "@ente/shared/apps/constants"; -import { EnteAppProps } from "@ente/shared/apps/types"; import { Overlay } from "@ente/shared/components/Container"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import { @@ -15,9 +13,9 @@ import HTTPService from "@ente/shared/network/HTTPService"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; -import createEmotionCache from "@ente/shared/themes/createEmotionCache"; import { CssBaseline, useMediaQuery } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; +import { AppProps } from "next/app"; import Head from "next/head"; import { useRouter } from "next/router"; import { createContext, useEffect, useState } from "react"; @@ -31,10 +29,7 @@ interface AppContextProps { export const AppContext = createContext({} as AppContextProps); -// Client-side cache, shared for the whole session of the user in the browser. -const clientSideEmotionCache = createEmotionCache(); - -export default function App(props: EnteAppProps) { +export default function App(props: AppProps) { const [isI18nReady, setIsI18nReady] = useState(false); const [showNavbar, setShowNavBar] = useState(false); @@ -54,11 +49,7 @@ export default function App(props: EnteAppProps) { const router = useRouter(); - const { - Component, - emotionCache = clientSideEmotionCache, - pageProps, - } = props; + const { Component, pageProps } = props; const [themeColor] = useLocalState(LS_KEYS.THEME, THEME_COLOR.DARK); @@ -87,7 +78,7 @@ export default function App(props: EnteAppProps) { // TODO: Localise APP_TITLES return ( - + <> {APP_TITLES.get(APPS.ACCOUNTS)} } - + ); } diff --git a/web/apps/accounts/src/pages/_document.tsx b/web/apps/accounts/src/pages/_document.tsx index 09d4d5782..3c6c2a959 100644 --- a/web/apps/accounts/src/pages/_document.tsx +++ b/web/apps/accounts/src/pages/_document.tsx @@ -1,7 +1,3 @@ -import DocumentPage, { - EnteDocumentProps, -} from "@ente/shared/next/pages/_document"; +import DocumentPage from "@ente/shared/next/pages/_document"; -export default function Document(props: EnteDocumentProps) { - return ; -} +export default DocumentPage; diff --git a/web/apps/auth/src/pages/_app.tsx b/web/apps/auth/src/pages/_app.tsx index a8fa87e28..06dfc2402 100644 --- a/web/apps/auth/src/pages/_app.tsx +++ b/web/apps/auth/src/pages/_app.tsx @@ -1,7 +1,9 @@ -import AppNavbar from "@ente/shared/components/Navbar/app"; -import { t } from "i18next"; -import { createContext, useEffect, useRef, useState } from "react"; - +import { setupI18n } from "@/ui/i18n"; +import { + APPS, + APP_TITLES, + CLIENT_PACKAGE_NAMES, +} from "@ente/shared/apps/constants"; import { Overlay } from "@ente/shared/components/Container"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import { @@ -10,32 +12,26 @@ import { } from "@ente/shared/components/DialogBoxV2/types"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { MessageContainer } from "@ente/shared/components/MessageContainer"; +import AppNavbar from "@ente/shared/components/Navbar/app"; +import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; +import { useLocalState } from "@ente/shared/hooks/useLocalState"; import { clearLogsIfLocalStorageLimitExceeded, logStartupMessage, } from "@ente/shared/logging/web"; import HTTPService from "@ente/shared/network/HTTPService"; import { LS_KEYS } from "@ente/shared/storage/localStorage"; -import { CssBaseline, useMediaQuery } from "@mui/material"; -import { ThemeProvider } from "@mui/material/styles"; -import Head from "next/head"; -import { useRouter } from "next/router"; -import LoadingBar from "react-top-loading-bar"; - -import { setupI18n } from "@/ui/i18n"; -import { CacheProvider } from "@emotion/react"; -import { - APP_TITLES, - APPS, - CLIENT_PACKAGE_NAMES, -} from "@ente/shared/apps/constants"; -import { EnteAppProps } from "@ente/shared/apps/types"; -import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; -import { useLocalState } from "@ente/shared/hooks/useLocalState"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; -import createEmotionCache from "@ente/shared/themes/createEmotionCache"; import { SetTheme } from "@ente/shared/themes/types"; +import { CssBaseline, useMediaQuery } from "@mui/material"; +import { ThemeProvider } from "@mui/material/styles"; +import { t } from "i18next"; +import { AppProps } from "next/app"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import { createContext, useEffect, useRef, useState } from "react"; +import LoadingBar from "react-top-loading-bar"; import "../../public/css/global.css"; type AppContextType = { @@ -51,15 +47,8 @@ type AppContextType = { export const AppContext = createContext(null); -// Client-side cache, shared for the whole session of the user in the browser. -const clientSideEmotionCache = createEmotionCache(); - -export default function App(props: EnteAppProps) { - const { - Component, - emotionCache = clientSideEmotionCache, - pageProps, - } = props; +export default function App(props: AppProps) { + const { Component, pageProps } = props; const router = useRouter(); const [isI18nReady, setIsI18nReady] = useState(false); const [loading, setLoading] = useState(false); @@ -141,7 +130,7 @@ export default function App(props: EnteAppProps) { }); return ( - + <> {isI18nReady @@ -200,6 +189,6 @@ export default function App(props: EnteAppProps) { )} </AppContext.Provider> </ThemeProvider> - </CacheProvider> + </> ); } diff --git a/web/apps/auth/src/pages/_document.tsx b/web/apps/auth/src/pages/_document.tsx index 09d4d5782..3c6c2a959 100644 --- a/web/apps/auth/src/pages/_document.tsx +++ b/web/apps/auth/src/pages/_document.tsx @@ -1,7 +1,3 @@ -import DocumentPage, { - EnteDocumentProps, -} from "@ente/shared/next/pages/_document"; +import DocumentPage from "@ente/shared/next/pages/_document"; -export default function Document(props: EnteDocumentProps) { - return <DocumentPage {...props} />; -} +export default DocumentPage; diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index fe941f79c..ada902cbc 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -1,15 +1,9 @@ -import AppNavbar from "@ente/shared/components/Navbar/app"; -import { t } from "i18next"; -import { createContext, useEffect, useRef, useState } from "react"; - import { setupI18n } from "@/ui/i18n"; -import { CacheProvider } from "@emotion/react"; import { - APP_TITLES, APPS, + APP_TITLES, CLIENT_PACKAGE_NAMES, } from "@ente/shared/apps/constants"; -import { EnteAppProps } from "@ente/shared/apps/types"; import { Overlay } from "@ente/shared/components/Container"; import DialogBox from "@ente/shared/components/DialogBox"; import { @@ -23,11 +17,12 @@ import { } from "@ente/shared/components/DialogBoxV2/types"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { MessageContainer } from "@ente/shared/components/MessageContainer"; +import AppNavbar from "@ente/shared/components/Navbar/app"; import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; import ElectronAPIs from "@ente/shared/electron"; import { AppUpdateInfo } from "@ente/shared/electron/types"; import { CustomError } from "@ente/shared/error"; -import { eventBus, Events } from "@ente/shared/events"; +import { Events, eventBus } from "@ente/shared/events"; import { useLocalState } from "@ente/shared/hooks/useLocalState"; import { addLogLine } from "@ente/shared/logging"; import { @@ -36,7 +31,7 @@ import { } from "@ente/shared/logging/web"; import HTTPService from "@ente/shared/network/HTTPService"; import { logError } from "@ente/shared/sentry"; -import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; +import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { getLocalMapEnabled, getToken, @@ -44,7 +39,6 @@ import { } from "@ente/shared/storage/localStorage/helpers"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; -import createEmotionCache from "@ente/shared/themes/createEmotionCache"; import { SetTheme } from "@ente/shared/themes/types"; import ArrowForward from "@mui/icons-material/ArrowForward"; import { CssBaseline, useMediaQuery } from "@mui/material"; @@ -52,10 +46,13 @@ import { ThemeProvider } from "@mui/material/styles"; import "bootstrap/dist/css/bootstrap.min.css"; import Notification from "components/Notification"; import { REDIRECTS } from "constants/redirects"; +import { t } from "i18next"; import isElectron from "is-electron"; +import { AppProps } from "next/app"; import Head from "next/head"; import { useRouter } from "next/router"; import "photoswipe/dist/photoswipe.css"; +import { createContext, useEffect, useRef, useState } from "react"; import LoadingBar from "react-top-loading-bar"; import DownloadManager from "services/download"; import exportService from "services/export"; @@ -115,15 +112,8 @@ type AppContextType = { export const AppContext = createContext<AppContextType>(null); -// Client-side cache, shared for the whole session of the user in the browser. -const clientSideEmotionCache = createEmotionCache(); - -export default function App(props: EnteAppProps) { - const { - Component, - emotionCache = clientSideEmotionCache, - pageProps, - } = props; +export default function App(props: AppProps) { + const { Component, pageProps } = props; const router = useRouter(); const [isI18nReady, setIsI18nReady] = useState<boolean>(false); const [loading, setLoading] = useState(false); @@ -390,7 +380,7 @@ export default function App(props: EnteAppProps) { }); return ( - <CacheProvider value={emotionCache}> + <> <Head> <title> {isI18nReady @@ -491,6 +481,6 @@ export default function App(props: EnteAppProps) { )} </AppContext.Provider> </ThemeProvider> - </CacheProvider> + </> ); } diff --git a/web/apps/photos/src/pages/_document.tsx b/web/apps/photos/src/pages/_document.tsx index 09d4d5782..3c6c2a959 100644 --- a/web/apps/photos/src/pages/_document.tsx +++ b/web/apps/photos/src/pages/_document.tsx @@ -1,7 +1,3 @@ -import DocumentPage, { - EnteDocumentProps, -} from "@ente/shared/next/pages/_document"; +import DocumentPage from "@ente/shared/next/pages/_document"; -export default function Document(props: EnteDocumentProps) { - return <DocumentPage {...props} />; -} +export default DocumentPage; diff --git a/web/packages/shared/apps/types.ts b/web/packages/shared/apps/types.ts index 364342516..fa2f97232 100644 --- a/web/packages/shared/apps/types.ts +++ b/web/packages/shared/apps/types.ts @@ -1,14 +1,8 @@ -import { EmotionCache } from "@emotion/react"; import { TwoFactorType } from "@ente/accounts/constants/twofactor"; import { SetDialogBoxAttributesV2 } from "@ente/shared/components/DialogBoxV2/types"; -import { AppProps } from "next/app"; import { NextRouter } from "next/router"; import { APPS } from "./constants"; -export interface EnteAppProps extends AppProps { - emotionCache?: EmotionCache; -} - export interface PageProps { appContext: { showNavBar: (show: boolean) => void; diff --git a/web/packages/shared/next/pages/_document.tsx b/web/packages/shared/next/pages/_document.tsx index a18df1a2a..77fa25197 100644 --- a/web/packages/shared/next/pages/_document.tsx +++ b/web/packages/shared/next/pages/_document.tsx @@ -1,23 +1,6 @@ -import Document, { - DocumentContext, - DocumentProps, - Head, - Html, - Main, - NextScript, -} from "next/document"; -import React from "react"; +import { Head, Html, Main, NextScript } from "next/document"; -import createEmotionServer from "@emotion/server/create-instance"; -import { EnteAppProps } from "@ente/shared/apps/types"; -import createEmotionCache from "@ente/shared/themes/createEmotionCache"; -import { AppType } from "next/app"; - -export interface EnteDocumentProps extends DocumentProps { - emotionStyleTags: JSX.Element[]; -} - -export default function EnteDocument({ emotionStyleTags }: EnteDocumentProps) { +export default function EnteDocument() { return ( <Html lang="en"> <Head> @@ -27,7 +10,6 @@ export default function EnteDocument({ emotionStyleTags }: EnteDocumentProps) { /> <link rel="icon" href="/images/favicon.png" type="image/png" /> <meta name="apple-mobile-web-app-capable" content="yes" /> - {emotionStyleTags} </Head> <body> <Main /> @@ -36,67 +18,3 @@ export default function EnteDocument({ emotionStyleTags }: EnteDocumentProps) { </Html> ); } - -// `getInitialProps` belongs to `_document` (instead of `_app`), -// it's compatible with static-site generation (SSG). -EnteDocument.getInitialProps = async (ctx: DocumentContext) => { - // Resolution order - // - // On the server: - // 1. app.getInitialProps - // 2. page.getInitialProps - // 3. document.getInitialProps - // 4. app.render - // 5. page.render - // 6. document.render - // - // On the server with error: - // 1. document.getInitialProps - // 2. app.render - // 3. page.render - // 4. document.render - // - // On the client - // 1. app.getInitialProps - // 2. page.getInitialProps - // 3. app.render - // 4. page.render - - const originalRenderPage = ctx.renderPage; - - // You can consider sharing the same Emotion cache between all the SSR requests to speed up performance. - // However, be aware that it can have global side effects. - const cache = createEmotionCache(); - // eslint-disable-next-line @typescript-eslint/unbound-method - const { extractCriticalToChunks } = createEmotionServer(cache); - - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: ( - App: React.ComponentType< - React.ComponentProps<AppType> & EnteAppProps - >, - ) => - function EnhanceApp(props) { - return <App emotionCache={cache} {...props} />; - }, - }); - - const initialProps = await Document.getInitialProps(ctx); - // This is important. It prevents Emotion to render invalid HTML. - // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153 - const emotionStyles = extractCriticalToChunks(initialProps.html); - const emotionStyleTags = emotionStyles.styles.map((style) => ( - <style - data-emotion={`${style.key} ${style.ids.join(" ")}`} - key={style.key} - // eslint-disable-next-line react/no-danger - dangerouslySetInnerHTML={{ __html: style.css }} - /> - )); - - return { - ...initialProps, - emotionStyleTags, - }; -}; diff --git a/web/packages/shared/themes/createEmotionCache.ts b/web/packages/shared/themes/createEmotionCache.ts deleted file mode 100644 index 216e285f6..000000000 --- a/web/packages/shared/themes/createEmotionCache.ts +++ /dev/null @@ -1,19 +0,0 @@ -import createCache from "@emotion/cache"; - -const isBrowser = typeof document !== "undefined"; - -// On the client side, Create a meta tag at the top of the <head> and set it as insertionPoint. -// This assures that MUI styles are loaded first. -// It allows developers to easily override MUI styles with other styling solutions, like CSS modules. -export default function createEmotionCache() { - let insertionPoint; - - if (isBrowser) { - const emotionInsertionPoint = document.querySelector<HTMLMetaElement>( - 'meta[name="emotion-insertion-point"]', - ); - insertionPoint = emotionInsertionPoint ?? undefined; - } - - return createCache({ key: "mui-style", insertionPoint }); -}