refactor(plugin-infra): workspace loading (#3222)

This commit is contained in:
Alex Yang 2023-07-13 23:52:06 +08:00 committed by GitHub
parent 23ac82f845
commit 1f5995ffc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 70 additions and 42 deletions

View File

@ -22,7 +22,9 @@
"templates", "templates",
"y-indexeddb", "y-indexeddb",
"debug", "debug",
"storage" "storage",
"infra",
"plugin-infra"
] ]
] ]
} }

View File

@ -19,7 +19,7 @@ import {
import { createIndexedDBDownloadProvider } from '@affine/workspace/providers'; import { createIndexedDBDownloadProvider } from '@affine/workspace/providers';
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import { nanoid } from '@blocksuite/store'; import { nanoid } from '@blocksuite/store';
import { useStaticBlockSuiteWorkspace } from '@toeverything/hooks/use-block-suite-workspace'; import { useStaticBlockSuiteWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import { import {
BlockSuitePageList, BlockSuitePageList,

View File

@ -6,8 +6,8 @@ import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { RootWorkspaceMetadata } from '@affine/workspace/atom'; import type { RootWorkspaceMetadata } from '@affine/workspace/atom';
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import { useStaticBlockSuiteWorkspace } from '@toeverything/hooks/use-block-suite-workspace';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import { useStaticBlockSuiteWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import clsx from 'clsx'; import clsx from 'clsx';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import type { FC } from 'react'; import type { FC } from 'react';

View File

@ -1,5 +1,5 @@
import { WorkspaceDetailSkeleton } from '@affine/component/setting-components'; import { WorkspaceDetailSkeleton } from '@affine/component/setting-components';
import { usePassiveWorkspaceEffect } from '@toeverything/hooks/use-block-suite-workspace'; import { usePassiveWorkspaceEffect } from '@toeverything/plugin-infra/__internal__/workspace';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { Suspense, useCallback } from 'react'; import { Suspense, useCallback } from 'react';

View File

@ -1,7 +1,7 @@
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
import { useStaticBlockSuiteWorkspace } from '@toeverything/hooks/use-block-suite-workspace'; import { useStaticBlockSuiteWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import type { Atom } from 'jotai'; import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai'; import { atom, useAtomValue } from 'jotai';

View File

@ -4,7 +4,7 @@ import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import { saveWorkspaceToLocalStorage } from '@affine/workspace/local/crud'; import { saveWorkspaceToLocalStorage } from '@affine/workspace/local/crud';
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import { nanoid } from '@blocksuite/store'; import { nanoid } from '@blocksuite/store';
import { getWorkspace } from '@toeverything/hooks/use-block-suite-workspace'; import { getWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import { useAtomValue, useSetAtom } from 'jotai'; import { useAtomValue, useSetAtom } from 'jotai';
import { useCallback } from 'react'; import { useCallback } from 'react';

View File

@ -32,8 +32,8 @@ import {
useSensor, useSensor,
useSensors, useSensors,
} from '@dnd-kit/core'; } from '@dnd-kit/core';
import { usePassiveWorkspaceEffect } from '@toeverything/hooks/use-block-suite-workspace';
import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper';
import { usePassiveWorkspaceEffect } from '@toeverything/plugin-infra/__internal__/workspace';
import { import {
currentPageIdAtom, currentPageIdAtom,
currentWorkspaceIdAtom, currentWorkspaceIdAtom,

View File

@ -2,7 +2,7 @@ import { WorkspaceFallback } from '@affine/component/workspace';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import { WorkspaceSubPath } from '@affine/env/workspace'; import { WorkspaceSubPath } from '@affine/env/workspace';
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import { getWorkspace } from '@toeverything/hooks/use-block-suite-workspace'; import { getWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import type { NextPage } from 'next'; import type { NextPage } from 'next';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';

View File

@ -12,7 +12,6 @@ export const BlockHubWrapper = (props: BlockHubProps): ReactElement => {
const blockHub = useAtomValue(props.blockHubAtom); const blockHub = useAtomValue(props.blockHubAtom);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
console.log('ref.current', blockHub, ref);
if (ref.current) { if (ref.current) {
const div = ref.current; const div = ref.current;
if (blockHub) { if (blockHub) {

View File

@ -8,8 +8,8 @@ import {
LocalDataIcon as DefaultLocalDataIcon, LocalDataIcon as DefaultLocalDataIcon,
LocalWorkspaceIcon as DefaultLocalWorkspaceIcon, LocalWorkspaceIcon as DefaultLocalWorkspaceIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import { useStaticBlockSuiteWorkspace } from '@toeverything/hooks/use-block-suite-workspace';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import { useStaticBlockSuiteWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import type { FC } from 'react'; import type { FC } from 'react';
import { useCallback } from 'react'; import { useCallback } from 'react';

View File

@ -18,17 +18,19 @@
"type": "./dist/type.d.ts", "type": "./dist/type.d.ts",
"import": "./dist/type.js", "import": "./dist/type.js",
"require": "./dist/type.cjs" "require": "./dist/type.cjs"
},
"./__internal__/workspace": {
"type": "./dist/__internal__/workspace.d.ts",
"import": "./dist/__internal__/workspace.js",
"require": "./dist/__internal__/workspace.cjs"
} }
}, },
"dependencies": { "devDependencies": {
"@blocksuite/blocks": "0.0.0-20230713062147-9eb7708c-nightly", "@blocksuite/blocks": "0.0.0-20230713062147-9eb7708c-nightly",
"@blocksuite/editor": "0.0.0-20230713062147-9eb7708c-nightly", "@blocksuite/editor": "0.0.0-20230713062147-9eb7708c-nightly",
"@blocksuite/global": "0.0.0-20230713062147-9eb7708c-nightly", "@blocksuite/global": "0.0.0-20230713062147-9eb7708c-nightly",
"@blocksuite/lit": "0.0.0-20230713062147-9eb7708c-nightly", "@blocksuite/lit": "0.0.0-20230713062147-9eb7708c-nightly",
"@blocksuite/store": "0.0.0-20230713062147-9eb7708c-nightly", "@blocksuite/store": "0.0.0-20230713062147-9eb7708c-nightly",
"jotai": "^2.2.2"
},
"devDependencies": {
"jotai": "^2.2.2", "jotai": "^2.2.2",
"vite": "^4.3.9", "vite": "^4.3.9",
"vite-plugin-dts": "3.0.2" "vite-plugin-dts": "3.0.2"

View File

@ -17,10 +17,25 @@ const workspacePassiveAtomWeakMap = new WeakMap<
>(); >();
// Whether the workspace is active to use // Whether the workspace is active to use
const workspaceActiveWeakMap = new WeakMap<Workspace, boolean>(); export const workspaceActiveWeakMap = new WeakMap<Workspace, boolean>();
// Whether the workspace has been enabled the passive effect (background) // Whether the workspace has been enabled the passive effect (background)
const workspacePassiveEffectWeakMap = new WeakMap<Workspace, boolean>(); export const workspacePassiveEffectWeakMap = new WeakMap<Workspace, boolean>();
export async function waitForWorkspace(workspace: Workspace) {
if (workspaceActiveWeakMap.get(workspace) !== true) {
const providers = workspace.providers.filter(
(provider): provider is ActiveDocProvider =>
'active' in provider && provider.active === true
);
for (const provider of providers) {
provider.sync();
// we will wait for the necessary providers to be ready
await provider.whenReady;
}
workspaceActiveWeakMap.set(workspace, true);
}
}
export function getWorkspace(id: string) { export function getWorkspace(id: string) {
if (!INTERNAL_BLOCKSUITE_HASH_MAP.has(id)) { if (!INTERNAL_BLOCKSUITE_HASH_MAP.has(id)) {
@ -38,18 +53,7 @@ export function getActiveBlockSuiteWorkspaceAtom(
const workspace = INTERNAL_BLOCKSUITE_HASH_MAP.get(id) as Workspace; const workspace = INTERNAL_BLOCKSUITE_HASH_MAP.get(id) as Workspace;
if (!workspacePassiveAtomWeakMap.has(workspace)) { if (!workspacePassiveAtomWeakMap.has(workspace)) {
const baseAtom = atom(async () => { const baseAtom = atom(async () => {
if (workspaceActiveWeakMap.get(workspace) !== true) { await waitForWorkspace(workspace);
const providers = workspace.providers.filter(
(provider): provider is ActiveDocProvider =>
'active' in provider && provider.active === true
);
for (const provider of providers) {
provider.sync();
// we will wait for the necessary providers to be ready
await provider.whenReady;
}
workspaceActiveWeakMap.set(workspace, true);
}
return workspace; return workspace;
}); });
workspacePassiveAtomWeakMap.set(workspace, baseAtom); workspacePassiveAtomWeakMap.set(workspace, baseAtom);

View File

@ -3,14 +3,15 @@
*/ */
import { Workspace } from '@blocksuite/store'; import { Workspace } from '@blocksuite/store';
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import { getDefaultStore } from 'jotai/vanilla';
import { expect, test, vi } from 'vitest';
import { import {
getActiveBlockSuiteWorkspaceAtom, getActiveBlockSuiteWorkspaceAtom,
INTERNAL_BLOCKSUITE_HASH_MAP, INTERNAL_BLOCKSUITE_HASH_MAP,
usePassiveWorkspaceEffect, usePassiveWorkspaceEffect,
useStaticBlockSuiteWorkspace, useStaticBlockSuiteWorkspace,
} from '@toeverything/hooks/use-block-suite-workspace'; } from '../__internal__/workspace';
import { getDefaultStore } from 'jotai/vanilla';
import { expect, test, vi } from 'vitest';
test('useStaticBlockSuiteWorkspace', async () => { test('useStaticBlockSuiteWorkspace', async () => {
const sync = vi.fn(); const sync = vi.fn();

View File

@ -1,5 +1,8 @@
import { assertExists } from '@blocksuite/global/utils';
import type { Page, Workspace } from '@blocksuite/store';
import { atom, createStore } from 'jotai/vanilla'; import { atom, createStore } from 'jotai/vanilla';
import { getWorkspace, waitForWorkspace } from './__internal__/workspace';
import type { AffinePlugin, Definition, ServerAdapter } from './type'; import type { AffinePlugin, Definition, ServerAdapter } from './type';
import type { Loader, PluginUIAdapter } from './type'; import type { Loader, PluginUIAdapter } from './type';
import type { PluginBlockSuiteAdapter } from './type'; import type { PluginBlockSuiteAdapter } from './type';
@ -12,8 +15,29 @@ export const rootStore = createStore();
// todo: for now every plugin is enabled by default // todo: for now every plugin is enabled by default
export const affinePluginsAtom = atom<Record<string, AffinePlugin<string>>>({}); export const affinePluginsAtom = atom<Record<string, AffinePlugin<string>>>({});
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceIdAtom = atom<string | null>(null); export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceAtom = atom<Promise<Workspace>>(async get => {
const currentWorkspaceId = get(currentWorkspaceIdAtom);
assertExists(currentWorkspaceId, 'current workspace id');
const workspace = getWorkspace(currentWorkspaceId);
await waitForWorkspace(workspace);
return workspace;
});
export const currentPageAtom = atom<Promise<Page>>(async get => {
const currentWorkspaceId = get(currentWorkspaceIdAtom);
assertExists(currentWorkspaceId, 'current workspace id');
const currentPageId = get(currentPageIdAtom);
assertExists(currentPageId, 'current page id');
const workspace = getWorkspace(currentWorkspaceId);
await waitForWorkspace(workspace);
const page = workspace.getPage(currentPageId);
assertExists(page);
if (!page.loaded) {
await page.waitForLoaded();
}
return page;
});
export function definePlugin<ID extends string>( export function definePlugin<ID extends string>(
definition: Definition<ID>, definition: Definition<ID>,

View File

@ -13,18 +13,14 @@ export default defineConfig({
entry: { entry: {
type: resolve(root, 'src/type.ts'), type: resolve(root, 'src/type.ts'),
manager: resolve(root, 'src/manager.ts'), manager: resolve(root, 'src/manager.ts'),
'__internal__/workspace': resolve(
root,
'src/__internal__/workspace.ts'
),
}, },
}, },
rollupOptions: { rollupOptions: {
external: [ external: ['react', /^jotai/, /^@blocksuite/],
'jotai',
'jotai/vanilla',
'@blocksuite/blocks',
'@blocksuite/store',
'@blocksuite/global',
'@blocksuite/editor',
'@blocksuite/lit',
],
}, },
}, },
plugins: [ plugins: [

View File

@ -12,7 +12,7 @@ import {
Generator, Generator,
Workspace, Workspace,
} from '@blocksuite/store'; } from '@blocksuite/store';
import { INTERNAL_BLOCKSUITE_HASH_MAP } from '@toeverything/hooks/use-block-suite-workspace'; import { INTERNAL_BLOCKSUITE_HASH_MAP } from '@toeverything/plugin-infra/__internal__/workspace';
import { createStaticStorage } from './blob/local-static-storage'; import { createStaticStorage } from './blob/local-static-storage';
import { createSQLiteStorage } from './blob/sqlite-blob-storage'; import { createSQLiteStorage } from './blob/sqlite-blob-storage';