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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 35 deletions

View File

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

View File

@ -16,7 +16,6 @@ import { AffineErrorBoundary } from '../components/affine/affine-error-eoundary'
import { ProviderComposer } from '../components/provider-composer';
import { PageLoading } from '../components/pure/loading';
import { MessageCenter } from '../components/pure/message-center';
import { AffineSWRConfigProvider } from '../providers/AffineSWRConfigProvider';
import { ThemeProvider } from '../providers/ThemeProvider';
import type { NextPageWithLayout } from '../shared';
import createEmotionCache from '../utils/create-emotion-cache';
@ -57,7 +56,6 @@ const App = function App({
<ProviderComposer
contexts={useMemo(
() => [
<AffineSWRConfigProvider key="AffineSWRConfigProvider" />,
<Provider key="JotaiProvider" store={jotaiStore} />,
<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 { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { PageDetailEditor } from '../../components/page-detail-editor';
import { AffineSWRConfigProvider } from '../../providers/AffineSWRConfigProvider';
import { BlockSuiteWorkspace } from '../../shared';
import { affineApis } from '../../shared/apis';
import { initPage } from '../../utils';
@ -199,6 +200,9 @@ export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = {
},
},
UI: {
Provider: ({ children }) => {
return <AffineSWRConfigProvider>{children}</AffineSWRConfigProvider>;
},
PageDetail: ({ currentWorkspace, currentPageId }) => {
const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
if (!page) {

View File

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

View File

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