feat: support enable/disable plugin (#3605)

This commit is contained in:
Alex Yang
2023-08-07 20:58:31 -04:00
committed by GitHub
parent ec05bd3f53
commit b147624f1c
14 changed files with 434 additions and 209 deletions
+4 -9
View File
@@ -30,15 +30,10 @@
"import": "./dist/type.js",
"require": "./dist/type.cjs"
},
"./__internal__/workspace": {
"type": "./dist/src/__internal__/workspace.d.ts",
"import": "./dist/__internal__/workspace.js",
"require": "./dist/__internal__/workspace.cjs"
},
"./__internal__/react": {
"type": "./dist/src/__internal__/react.d.ts",
"import": "./dist/__internal__/react.js",
"require": "./dist/__internal__/react.cjs"
"./__internal__/*": {
"type": "./dist/src/__internal__/*.d.ts",
"import": "./dist/__internal__/*.js",
"require": "./dist/__internal__/*.cjs"
}
},
"files": [
+51
View File
@@ -0,0 +1,51 @@
import type { CallbackMap } from '@affine/sdk/entry';
import { atomWithStorage } from 'jotai/utils';
import { atom } from 'jotai/vanilla';
import type { z } from 'zod';
import type { packageJsonOutputSchema } from '../type.js';
export const builtinPluginPaths = new Set([
'/plugins/bookmark',
'/plugins/copilot',
'/plugins/hello-world',
'/plugins/image-preview',
'/plugins/vue-hello-world',
]);
const pluginCleanupMap = new Map<string, (() => void)[]>();
export function addCleanup(pluginName: string, cleanup: () => void) {
if (!pluginCleanupMap.has(pluginName)) {
pluginCleanupMap.set(pluginName, []);
}
pluginCleanupMap.get(pluginName)?.push(cleanup);
}
export function invokeCleanup(pluginName: string) {
pluginCleanupMap.get(pluginName)?.forEach(cleanup => cleanup());
pluginCleanupMap.delete(pluginName);
}
export const pluginPackageJson = atom<
z.infer<typeof packageJsonOutputSchema>[]
>([]);
export const enabledPluginAtom = atomWithStorage('affine-enabled-plugin', [
'@affine/bookmark-plugin',
'@affine/image-preview-plugin',
]);
export const pluginHeaderItemAtom = atom<
Record<string, CallbackMap['headerItem']>
>({});
export const pluginSettingAtom = atom<Record<string, CallbackMap['setting']>>(
{}
);
export const pluginEditorAtom = atom<Record<string, CallbackMap['editor']>>({});
export const pluginWindowAtom = atom<
Record<string, (root: HTMLElement) => () => void>
>({});
+2 -15
View File
@@ -1,4 +1,4 @@
import type { CallbackMap, ExpectedLayout } from '@affine/sdk/entry';
import type { ExpectedLayout } from '@affine/sdk/entry';
import { assertExists } from '@blocksuite/global/utils';
import type { Page, Workspace } from '@blocksuite/store';
import { atom, createStore } from 'jotai/vanilla';
@@ -7,20 +7,7 @@ import { getWorkspace, waitForWorkspace } from './__internal__/workspace.js';
// global store
export const rootStore = createStore();
// id -> HTML element
export const headerItemsAtom = atom<Record<string, CallbackMap['headerItem']>>(
{}
);
export const editorItemsAtom = atom<Record<string, CallbackMap['editor']>>({});
export const registeredPluginAtom = atom<string[]>([]);
export const windowItemsAtom = atom<Record<string, CallbackMap['window']>>({});
export const settingItemsAtom = atom<Record<string, CallbackMap['setting']>>(
{}
);
export const formatBarItemsAtom = atom<
Record<string, CallbackMap['formatBar']>
>({});
export const loadedPluginNameAtom = atom<string[]>([]);
export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
+1
View File
@@ -21,6 +21,7 @@ export default defineConfig({
'src/__internal__/workspace.ts'
),
'__internal__/react': resolve(root, 'src/__internal__/react.ts'),
'__internal__/plugin': resolve(root, 'src/__internal__/plugin.ts'),
},
formats: ['es', 'cjs'],
name: 'AffineInfra',
+11 -6
View File
@@ -2,14 +2,14 @@ import type { getCurrentBlockRange } from '@blocksuite/blocks';
import type { EditorContainer } from '@blocksuite/editor';
import type { Page } from '@blocksuite/store';
import type { Workspace } from '@blocksuite/store';
import type { Atom, getDefaultStore, PrimitiveAtom } from 'jotai/vanilla';
import type { Atom, getDefaultStore } from 'jotai/vanilla';
import type { WritableAtom } from 'jotai/vanilla/atom';
import type { FC } from 'react';
export type Part = 'headerItem' | 'editor' | 'window' | 'setting' | 'formatBar';
export type Part = 'headerItem' | 'editor' | 'setting' | 'formatBar';
export type CallbackMap = {
headerItem: (root: HTMLElement) => () => void;
window: (root: HTMLElement) => () => void;
editor: (root: HTMLElement, editor: EditorContainer) => () => void;
setting: (root: HTMLElement) => () => void;
formatBar: (
@@ -31,13 +31,13 @@ export type LayoutNode = LayoutParentNode | string;
export type LayoutParentNode = {
direction: LayoutDirection;
splitPercentage: number; // 0 - 100
first: LayoutNode;
first: string;
second: LayoutNode;
};
export type ExpectedLayout =
| {
direction: LayoutDirection;
direction: 'horizontal';
// the first element is always the editor
first: 'editor';
second: LayoutNode;
@@ -46,7 +46,12 @@ export type ExpectedLayout =
}
| 'editor';
export declare const contentLayoutAtom: PrimitiveAtom<ExpectedLayout>;
export declare const pushLayoutAtom: WritableAtom<
null,
[string, (div: HTMLDivElement) => () => void],
void
>;
export declare const deleteLayoutAtom: WritableAtom<null, [string], void>;
export declare const currentPageAtom: Atom<Promise<Page>>;
export declare const currentWorkspaceAtom: Atom<Promise<Workspace>>;
export declare const rootStore: ReturnType<typeof getDefaultStore>;