refactor: abstract workspace provider (#1809)

This commit is contained in:
Himself65
2023-04-03 23:28:00 -05:00
committed by GitHub
parent 67a5d1520d
commit 5129ab3db8
6 changed files with 28 additions and 35 deletions

View File

@@ -1,10 +1,9 @@
import { atomWithSyncStorage } from '@affine/jotai'; import { atomWithSyncStorage } from '@affine/jotai';
import { jotaiStore, jotaiWorkspacesAtom } from '@affine/workspace/atom'; import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
import type { EditorContainer } from '@blocksuite/editor'; import type { EditorContainer } from '@blocksuite/editor';
import type { Page } from '@blocksuite/store'; import type { Page } from '@blocksuite/store';
import { assertExists } from '@blocksuite/store'; import { assertExists } from '@blocksuite/store';
import { atom } from 'jotai'; import { atom } from 'jotai';
import { unstable_batchedUpdates } from 'react-dom';
import { WorkspacePlugins } from '../plugins'; import { WorkspacePlugins } from '../plugins';
import type { AllWorkspace } from '../shared'; import type { AllWorkspace } from '../shared';
@@ -13,22 +12,6 @@ export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null); export const currentPageIdAtom = atom<string | null>(null);
export const currentEditorAtom = atom<Readonly<EditorContainer> | null>(null); export const currentEditorAtom = atom<Readonly<EditorContainer> | null>(null);
// If the workspace is locked, it means that the user maybe updating the workspace
// from local to remote or vice versa
export const workspaceLockAtom = atom(false);
export async function lockMutex(fn: () => Promise<unknown>) {
if (jotaiStore.get(workspaceLockAtom)) {
throw new Error('Workspace is locked');
}
unstable_batchedUpdates(() => {
jotaiStore.set(workspaceLockAtom, true);
});
await fn();
unstable_batchedUpdates(() => {
jotaiStore.set(workspaceLockAtom, false);
});
}
// modal atoms // modal atoms
export const openWorkspacesModalAtom = atom(false); export const openWorkspacesModalAtom = atom(false);
export const openCreateWorkspaceModalAtom = atom(false); export const openCreateWorkspaceModalAtom = atom(false);

View File

@@ -10,14 +10,13 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import Head from 'next/head'; import Head from 'next/head';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import type React from 'react'; import type { FC, PropsWithChildren } from 'react';
import { Suspense, useCallback, useEffect } from 'react'; import { Suspense, useCallback, useEffect } from 'react';
import { import {
currentWorkspaceIdAtom, currentWorkspaceIdAtom,
openQuickSearchModalAtom, openQuickSearchModalAtom,
openWorkspacesModalAtom, openWorkspacesModalAtom,
workspaceLockAtom,
} from '../atoms'; } from '../atoms';
import { import {
publicBlockSuiteAtom, publicBlockSuiteAtom,
@@ -63,7 +62,7 @@ const QuickSearchModal = dynamic(
() => import('../components/pure/quick-search-modal') () => import('../components/pure/quick-search-modal')
); );
export const PublicQuickSearch: React.FC = () => { export const PublicQuickSearch: FC = () => {
const blockSuiteWorkspace = useAtomValue(publicBlockSuiteAtom); const blockSuiteWorkspace = useAtomValue(publicBlockSuiteAtom);
const router = useRouter(); const router = useRouter();
const [openQuickSearchModal, setOpenQuickSearchModalAtom] = useAtom( const [openQuickSearchModal, setOpenQuickSearchModalAtom] = useAtom(
@@ -79,7 +78,11 @@ export const PublicQuickSearch: React.FC = () => {
); );
}; };
export const QuickSearch: React.FC = () => { function DefaultProvider({ children }: PropsWithChildren) {
return <>{children}</>;
}
export const QuickSearch: FC = () => {
const [currentWorkspace] = useCurrentWorkspace(); const [currentWorkspace] = useCurrentWorkspace();
const router = useRouter(); const router = useRouter();
const [openQuickSearchModal, setOpenQuickSearchModalAtom] = useAtom( const [openQuickSearchModal, setOpenQuickSearchModalAtom] = useAtom(
@@ -110,7 +113,7 @@ const logger = new DebugLogger('workspace-layout');
const affineGlobalChannel = createAffineGlobalChannel( const affineGlobalChannel = createAffineGlobalChannel(
WorkspacePlugins[WorkspaceFlavour.AFFINE].CRUD WorkspacePlugins[WorkspaceFlavour.AFFINE].CRUD
); );
export const WorkspaceLayout: React.FC<React.PropsWithChildren> = export const WorkspaceLayout: FC<PropsWithChildren> =
function WorkspacesSuspense({ children }) { function WorkspacesSuspense({ children }) {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
useEffect(() => { useEffect(() => {
@@ -180,9 +183,7 @@ function AffineWorkspaceEffect() {
return null; return null;
} }
export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
children,
}) => {
const [currentWorkspace] = useCurrentWorkspace(); const [currentWorkspace] = useCurrentWorkspace();
const [currentPageId] = useCurrentPageId(); const [currentPageId] = useCurrentPageId();
const workspaces = useWorkspaces(); const workspaces = useWorkspaces();
@@ -260,7 +261,6 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
setOpenQuickSearchModalAtom(true); setOpenQuickSearchModalAtom(true);
}, [setOpenQuickSearchModalAtom]); }, [setOpenQuickSearchModalAtom]);
const [resizingSidebar, setIsResizing] = useSidebarResizing(); const [resizingSidebar, setIsResizing] = useSidebarResizing();
const lock = useAtomValue(workspaceLockAtom);
const [sidebarOpen, setSidebarOpen] = useSidebarStatus(); const [sidebarOpen, setSidebarOpen] = useSidebarStatus();
const sidebarFloating = useSidebarFloating(); const sidebarFloating = useSidebarFloating();
const [sidebarWidth, setSliderWidth] = useSidebarWidth(); const [sidebarWidth, setSliderWidth] = useSidebarWidth();
@@ -291,12 +291,16 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
); );
}, [setIsResizing, setSidebarOpen, setSliderWidth]); }, [setIsResizing, setSidebarOpen, setSliderWidth]);
if (lock) { const Provider = currentWorkspace
return <PageLoading />; ? WorkspacePlugins[currentWorkspace.flavour].UI.Provider
} : DefaultProvider;
return ( return (
<> <Provider
key={`${
currentWorkspace ? currentWorkspace.flavour : 'default'
}-provider`}
>
<Head> <Head>
<title>{title}</title> <title>{title}</title>
</Head> </Head>
@@ -353,6 +357,6 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
</MainContainerWrapper> </MainContainerWrapper>
</StyledPage> </StyledPage>
<QuickSearch /> <QuickSearch />
</> </Provider>
); );
}; };

View File

@@ -16,7 +16,6 @@ import { AffineErrorBoundary } from '../components/affine/affine-error-eoundary'
import { ProviderComposer } from '../components/provider-composer'; import { ProviderComposer } from '../components/provider-composer';
import { PageLoading } from '../components/pure/loading'; import { PageLoading } from '../components/pure/loading';
import { MessageCenter } from '../components/pure/message-center'; import { MessageCenter } from '../components/pure/message-center';
import { AffineSWRConfigProvider } from '../providers/AffineSWRConfigProvider';
import { ThemeProvider } from '../providers/ThemeProvider'; import { ThemeProvider } from '../providers/ThemeProvider';
import type { NextPageWithLayout } from '../shared'; import type { NextPageWithLayout } from '../shared';
import createEmotionCache from '../utils/create-emotion-cache'; import createEmotionCache from '../utils/create-emotion-cache';
@@ -57,7 +56,6 @@ const App = function App({
<ProviderComposer <ProviderComposer
contexts={useMemo( contexts={useMemo(
() => [ () => [
<AffineSWRConfigProvider key="AffineSWRConfigProvider" />,
<Provider key="JotaiProvider" store={jotaiStore} />, <Provider key="JotaiProvider" store={jotaiStore} />,
<ThemeProvider key="ThemeProvider" />, <ThemeProvider key="ThemeProvider" />,
], ],

View File

@@ -12,6 +12,7 @@ import { PageNotFoundError } from '../../components/affine/affine-error-eoundary
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail'; import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list'; import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { PageDetailEditor } from '../../components/page-detail-editor'; import { PageDetailEditor } from '../../components/page-detail-editor';
import { AffineSWRConfigProvider } from '../../providers/AffineSWRConfigProvider';
import { BlockSuiteWorkspace } from '../../shared'; import { BlockSuiteWorkspace } from '../../shared';
import { affineApis } from '../../shared/apis'; import { affineApis } from '../../shared/apis';
import { initPage } from '../../utils'; import { initPage } from '../../utils';
@@ -199,6 +200,9 @@ export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = {
}, },
}, },
UI: { UI: {
Provider: ({ children }) => {
return <AffineSWRConfigProvider>{children}</AffineSWRConfigProvider>;
},
PageDetail: ({ currentWorkspace, currentPageId }) => { PageDetail: ({ currentWorkspace, currentPageId }) => {
const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId); const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
if (!page) { if (!page) {

View File

@@ -14,6 +14,9 @@ export const LocalPlugin: WorkspacePlugin<WorkspaceFlavour.LOCAL> = {
loadPriority: LoadPriority.LOW, loadPriority: LoadPriority.LOW,
CRUD, CRUD,
UI: { UI: {
Provider: ({ children }) => {
return <>{children}</>;
},
PageDetail: ({ currentWorkspace, currentPageId }) => { PageDetail: ({ currentWorkspace, currentPageId }) => {
const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId); const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
if (!page) { if (!page) {

View File

@@ -1,6 +1,6 @@
import type { Workspace as RemoteWorkspace } from '@affine/workspace/affine/api'; import type { Workspace as RemoteWorkspace } from '@affine/workspace/affine/api';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
import type { FC } from 'react'; import type { FC, PropsWithChildren } from 'react';
export type BaseProvider = { export type BaseProvider = {
flavour: string; flavour: string;
@@ -126,4 +126,5 @@ export interface WorkspaceUISchema<Flavour extends keyof WorkspaceRegistry> {
PageDetail: FC<PageDetailProps<Flavour>>; PageDetail: FC<PageDetailProps<Flavour>>;
PageList: FC<PageListProps<Flavour>>; PageList: FC<PageListProps<Flavour>>;
SettingsDetail: FC<SettingProps<Flavour>>; SettingsDetail: FC<SettingProps<Flavour>>;
Provider: FC<PropsWithChildren>;
} }