mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-11 14:08:55 +08:00
refactor!: next generation AFFiNE code structure (#1176)
This commit is contained in:
+81
-92
@@ -1,107 +1,96 @@
|
||||
import '../../public/globals.css';
|
||||
import './temporary.css';
|
||||
import '@fontsource/space-mono';
|
||||
import '@fontsource/poppins';
|
||||
import '../utils/print-build-info';
|
||||
import '@affine/i18n';
|
||||
import '@blocksuite/editor/themes/affine.css';
|
||||
import '../styles/globals.css';
|
||||
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { Logger } from '@toeverything/pathfinder-logger';
|
||||
import type { NextPage } from 'next';
|
||||
import type { AppProps } from 'next/app';
|
||||
import Head from 'next/head';
|
||||
// import AppStateProvider2 from '@/providers/app-state-provider2/provider';
|
||||
import { appWithTranslation, createI18n, I18nextProvider } from '@affine/i18n';
|
||||
import createCache from '@emotion/cache';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import { Provider } from 'jotai';
|
||||
import { useAtomsDebugValue } from 'jotai-devtools';
|
||||
import { AppProps } from 'next/app';
|
||||
import { useRouter } from 'next/router';
|
||||
import type { PropsWithChildren, ReactElement, ReactNode } from 'react';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import React, { memo, ReactElement, Suspense, useEffect, useMemo } from 'react';
|
||||
import { Helmet, HelmetProvider } from 'react-helmet-async';
|
||||
import { SWRConfig, SWRConfiguration } from 'swr';
|
||||
|
||||
import { PageLoading } from '@/components/loading';
|
||||
import { MessageCenterHandler } from '@/components/message-center-handler';
|
||||
import ProviderComposer from '@/components/provider-composer';
|
||||
import { AppStateProvider } from '@/providers/app-state-provider';
|
||||
import ConfirmProvider from '@/providers/ConfirmProvider';
|
||||
import { ThemeProvider } from '@/providers/ThemeProvider';
|
||||
import { GlobalAppProvider } from '@/store/app';
|
||||
import { DataCenterPreloader } from '@/store/app/datacenter';
|
||||
import { ModalProvider } from '@/store/globalModal';
|
||||
|
||||
export type NextPageWithLayout<P = Record<string, unknown>, IP = P> = NextPage<
|
||||
P,
|
||||
IP
|
||||
> & {
|
||||
getLayout?: (page: ReactElement) => ReactNode;
|
||||
};
|
||||
import { jotaiStore } from '../atoms';
|
||||
import { AffineErrorBoundary } from '../components/affine/affine-error-eoundary';
|
||||
import { ProviderComposer } from '../components/provider-composer';
|
||||
import { PageLoading } from '../components/pure/loading';
|
||||
import { AffineSWRConfigProvider } from '../providers/AffineSWRConfigProvider';
|
||||
import { ModalProvider } from '../providers/ModalProvider';
|
||||
import { ThemeProvider } from '../providers/ThemeProvider';
|
||||
import { NextPageWithLayout } from '../shared';
|
||||
import { config } from '../shared/env';
|
||||
|
||||
type AppPropsWithLayout = AppProps & {
|
||||
Component: NextPageWithLayout;
|
||||
};
|
||||
|
||||
// Page list which do not rely on app state
|
||||
const NoNeedAppStatePageList = [
|
||||
'/404',
|
||||
'/public-workspace/[workspaceId]',
|
||||
'/public-workspace/[workspaceId]/[pageId]',
|
||||
];
|
||||
const App = ({ Component, pageProps }: AppPropsWithLayout) => {
|
||||
const getLayout = Component.getLayout || (page => page);
|
||||
const { i18n } = useTranslation();
|
||||
const router = useRouter();
|
||||
const EmptyLayout = (page: ReactElement) => page;
|
||||
|
||||
React.useEffect(() => {
|
||||
document.documentElement.lang = i18n.language;
|
||||
}, [i18n.language]);
|
||||
const DebugAtoms = memo(function DebugAtoms() {
|
||||
useAtomsDebugValue();
|
||||
return null;
|
||||
});
|
||||
|
||||
const helmetContext = {};
|
||||
|
||||
const defaultSWRConfig: SWRConfiguration = {
|
||||
suspense: true,
|
||||
fetcher: () => {
|
||||
const error = new Error(
|
||||
'you might forget to warp your page with AffineSWRConfigProvider'
|
||||
);
|
||||
console.log(error);
|
||||
throw error;
|
||||
},
|
||||
};
|
||||
|
||||
const cache = createCache({ key: 'affine' });
|
||||
|
||||
const App = function App({ Component, pageProps }: AppPropsWithLayout) {
|
||||
const getLayout = Component.getLayout || EmptyLayout;
|
||||
const i18n = useMemo(() => createI18n(), []);
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// I know what I'm doing
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
console.log('Runtime Preset', config);
|
||||
}, []);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<meta name="theme-color" content="#fafafa" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/icons/apple-touch-icon.png"
|
||||
/>
|
||||
<title>AFFiNE</title>
|
||||
</Head>
|
||||
<Logger />
|
||||
<GlobalAppProvider key="BlockSuiteProvider">
|
||||
<ProviderComposer
|
||||
contexts={[
|
||||
<ThemeProvider key="ThemeProvider" />,
|
||||
<AppStateProvider key="appStateProvider" />,
|
||||
<ModalProvider key="ModalProvider" />,
|
||||
<ConfirmProvider key="ConfirmProvider" />,
|
||||
]}
|
||||
>
|
||||
{NoNeedAppStatePageList.includes(router.route) ? (
|
||||
getLayout(<Component {...pageProps} />)
|
||||
) : (
|
||||
<Suspense fallback={<PageLoading />}>
|
||||
<DataCenterPreloader>
|
||||
<MessageCenterHandler>
|
||||
<AppDefender>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</AppDefender>
|
||||
</MessageCenterHandler>
|
||||
</DataCenterPreloader>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<CacheProvider value={cache}>
|
||||
<DebugAtoms />
|
||||
<SWRConfig value={defaultSWRConfig}>
|
||||
<AffineErrorBoundary router={useRouter()}>
|
||||
<Suspense fallback={<PageLoading key="RootPageLoading" />}>
|
||||
<ProviderComposer
|
||||
contexts={useMemo(
|
||||
() => [
|
||||
<AffineSWRConfigProvider key="AffineSWRConfigProvider" />,
|
||||
<Provider key="JotaiProvider" store={jotaiStore} />,
|
||||
<ThemeProvider key="ThemeProvider" />,
|
||||
<ModalProvider key="ModalProvider" />,
|
||||
],
|
||||
[]
|
||||
)}
|
||||
>
|
||||
<HelmetProvider key="HelmetProvider" context={helmetContext}>
|
||||
<Helmet>
|
||||
<title>AFFiNE</title>
|
||||
</Helmet>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</HelmetProvider>
|
||||
</ProviderComposer>
|
||||
</Suspense>
|
||||
)}
|
||||
</ProviderComposer>
|
||||
</GlobalAppProvider>
|
||||
</>
|
||||
</AffineErrorBoundary>
|
||||
</SWRConfig>
|
||||
</CacheProvider>
|
||||
</I18nextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const AppDefender = ({ children }: PropsWithChildren) => {
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
if (['/index.html', '/'].includes(router.asPath)) {
|
||||
router.replace('/workspace');
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default App;
|
||||
export default appWithTranslation(App as any);
|
||||
|
||||
Reference in New Issue
Block a user