feat: update blocksuite version & perfect file system function

This commit is contained in:
QiShaoXuan
2022-12-13 15:11:05 +08:00
parent ee59381c38
commit c753a23a98
8 changed files with 199 additions and 155 deletions
+3 -3
View File
@@ -9,10 +9,10 @@
"lint": "next lint"
},
"dependencies": {
"@blocksuite/blocks": "0.3.0-alpha.6",
"@blocksuite/editor": "0.3.0-alpha.6",
"@blocksuite/blocks": "0.3.0-alpha.7",
"@blocksuite/editor": "0.3.0-alpha.7",
"@blocksuite/icons": "^1.0.5",
"@blocksuite/store": "0.3.0-alpha.6",
"@blocksuite/store": "0.3.0-alpha.7",
"@emotion/css": "^11.10.0",
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
@@ -50,7 +50,7 @@ export const WorkSpaceSliderBar = () => {
const { triggerQuickSearchModal, triggerImportModal } = useModal();
const [show, setShow] = useState(false);
const [showSubFavorite, setShowSubFavorite] = useState(false);
const { createPage } = useEditor();
const { createPage, getPageMeta, openPage } = useEditor();
const router = useRouter();
return (
@@ -116,8 +116,10 @@ export const WorkSpaceSliderBar = () => {
</StyledListItem>
</Link>
<StyledNewPageButton
onClick={() => {
createPage();
onClick={async () => {
const page = await createPage();
const pageMeta = getPageMeta(page.id);
pageMeta && openPage(pageMeta.id);
}}
>
New Page
@@ -1,69 +1,34 @@
import type { EditorContainer } from '@blocksuite/editor';
import { createContext, useContext, useEffect, useRef, useState } from 'react';
import { createContext, useContext, useEffect, useState } from 'react';
import type { PropsWithChildren } from 'react';
import dynamic from 'next/dynamic';
import Loading from './loading';
import { Page, Workspace } from '@blocksuite/store';
import { BlockSchema } from '@blocksuite/editor/dist/block-loader';
import { useRouter } from 'next/router';
import { QueryContent } from '@blocksuite/store/dist/workspace/search';
export interface PageMeta {
id: string;
title: string;
favorite: boolean;
trash: boolean;
createDate: number;
trashDate: number | null;
}
import useEditorHandler from './useEditorHandler';
import { EditorHandlers, PageMeta } from './interface';
// Blocksuite has to be imported dynamically since it has a lot of effects
const DynamicEditor = dynamic(() => import('./initial-editor'), {
const DynamicEditor = dynamic(() => import('./editor-reactor'), {
ssr: false,
});
type EditorContextValue = {
mode: EditorContainer['mode'];
setMode: (mode: EditorContainer['mode']) => void;
currentPage: Page | null;
editor: EditorContainer | null;
currentPage: Page | void;
editor: EditorContainer | void;
pageList: PageMeta[];
} & EditorHandlers;
type EditorHandlers = {
createPage: (pageId?: string) => void;
openPage: (
pageId: string,
query?: { [key: string]: string }
) => Promise<boolean>;
deletePage: (pageId: string) => void;
recyclePage: (pageId: string) => void;
toggleDeletePage: (pageId: string) => void;
favoritePage: (pageId: string) => void;
unFavoritePage: (pageId: string) => void;
toggleFavoritePage: (pageId: string) => void;
permanentlyDeletePage: (pageId: string) => void;
search: (query: QueryContent) => any;
};
type EditorContextProps = PropsWithChildren<{}>;
export const EditorContext = createContext<EditorContextValue>({
mode: 'page',
setMode: () => {},
pageList: [],
currentPage: null,
editor: null,
createPage: () => {},
openPage: async () => {
return false;
},
deletePage: () => {},
recyclePage: () => {},
toggleDeletePage: () => {},
favoritePage: () => {},
unFavoritePage: () => {},
toggleFavoritePage: () => {},
permanentlyDeletePage: () => {},
search: () => {},
currentPage: undefined,
editor: undefined,
...({} as EditorHandlers),
});
export const useEditor = () => useContext(EditorContext);
@@ -71,14 +36,14 @@ export const useEditor = () => useContext(EditorContext);
export const EditorProvider = ({
children,
}: PropsWithChildren<EditorContextProps>) => {
const router = useRouter();
const blockSchemaRef = useRef<typeof BlockSchema | null>(null);
const [workspace, setWorkspace] = useState<Workspace | null>(null);
const [currentPage, setCurrentPage] = useState<Page | null>(null);
const [workspace, setWorkspace] = useState<Workspace>();
const [currentPage, setCurrentPage] = useState<Page>();
const [pageList, setPageList] = useState<PageMeta[]>([]);
const [editor, setEditor] = useState<EditorContainer | null>(null);
const [editor, setEditor] = useState<EditorContainer>();
const [mode, setMode] = useState<EditorContainer['mode']>('page');
const editorHandlers = useEditorHandler(workspace);
useEffect(() => {
const event = new CustomEvent('affine.switch-mode', { detail: mode });
window.dispatchEvent(event);
@@ -88,9 +53,9 @@ export const EditorProvider = ({
if (!workspace) {
return;
}
setPageList(workspace.meta.pages as PageMeta[]);
setPageList(workspace.meta.pageMetas as PageMeta[]);
workspace.meta.pagesUpdated.on(res => {
setPageList(workspace.meta.pages as PageMeta[]);
setPageList(workspace.meta.pageMetas as PageMeta[]);
});
return () => {
// TODO: Does it need to be removed?
@@ -98,67 +63,20 @@ export const EditorProvider = ({
};
}, [workspace]);
const editorHandler: EditorHandlers = {
createPage: (pageId = new Date().getTime().toString()) => {
blockSchemaRef.current &&
workspace?.createPage(pageId).register(blockSchemaRef.current);
},
openPage: (pageId, query = {}) => {
return router.push({
pathname: '/',
query: {
pageId,
...query,
},
});
},
deletePage: pageId => {
workspace?.setPageMeta(pageId, { trash: true });
},
recyclePage: pageId => {
workspace?.setPageMeta(pageId, { trash: false });
},
toggleDeletePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPageMeta(pageId, { trash: !pageMeta.trash });
}
},
favoritePage: pageId => {
workspace?.setPageMeta(pageId, { favorite: true });
},
permanentlyDeletePage: pageId => {
// TODO: workspace.meta.removePage or workspace.removePage?
workspace?.meta.removePage(pageId);
},
unFavoritePage: pageId => {
workspace?.setPageMeta(pageId, { favorite: true });
},
toggleFavoritePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPageMeta(pageId, { favorite: !pageMeta.favorite });
}
},
search: (query: QueryContent) => {
if (query) {
return workspace?.search(query);
}
},
};
return (
<EditorContext.Provider
value={{ editor, currentPage, mode, setMode, pageList, ...editorHandler }}
value={{
editor,
currentPage,
mode,
setMode,
pageList,
...editorHandlers,
}}
>
<DynamicEditor
workspace={workspace}
currentPage={currentPage}
setBlockSchema={blockSchema => {
if (!blockSchemaRef.current) {
blockSchemaRef.current = blockSchema;
}
}}
setEditor={setEditor}
setWorkspace={setWorkspace}
setCurrentPage={setCurrentPage}
@@ -2,6 +2,7 @@ import '@blocksuite/blocks';
import '@blocksuite/blocks/style';
import type { EditorContainer } from '@blocksuite/editor';
import { BlockSchema, createEditor } from '@blocksuite/editor';
import { generateDefaultPageId, initialPage } from './utils';
import { useEffect } from 'react';
import pkg from '../../../package.json';
import {
@@ -11,6 +12,7 @@ import {
Page,
} from '@blocksuite/store';
import { useRouter } from 'next/router';
import { createPage } from '@/providers/editor-provider/utils';
const getEditorParams = () => {
const providers = [];
@@ -22,9 +24,8 @@ const getEditorParams = () => {
);
providers.push(WebsocketDocProvider);
}
if (params.get('syncMode') === 'indexeddb') {
providers.push(IndexedDBDocProvider);
}
providers.push(IndexedDBDocProvider);
return {
room,
@@ -32,29 +33,25 @@ const getEditorParams = () => {
};
};
const InitialEditor = ({
const EditorReactor = ({
workspace,
currentPage,
setBlockSchema,
setEditor,
setWorkspace,
setCurrentPage,
}: {
workspace: Workspace | null;
currentPage: Page | null;
setBlockSchema: (blockSchema: typeof BlockSchema) => void;
workspace: Workspace | void;
currentPage: Page | void;
setEditor: (editor: EditorContainer) => void;
setWorkspace: (workspace: Workspace) => void;
setCurrentPage: (Page: Page) => void;
}) => {
setBlockSchema(BlockSchema);
const router = useRouter();
useEffect(() => {
const workspace = new Workspace({
...getEditorParams(),
});
}).register(BlockSchema);
//@ts-ignore
window.workspace = workspace;
const indexDBProvider = workspace.providers.find(
@@ -74,21 +71,20 @@ const InitialEditor = ({
return;
}
// const initialPageId =
// workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
// ?.id ??
// workspace.meta.pages[0]?.id ??
// 'page0';
const initialPageId =
workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
?.id ?? 'page0';
console.log('initialPageId', initialPageId);
workspace.meta.pageMetas.find(
p => p.id === (router.query.pageId as string)
)?.id ?? workspace.meta.pageMetas[0]?.id;
const initialPage = workspace
.createPage(initialPageId)
.register(BlockSchema);
setCurrentPage(initialPage);
if (!initialPageId) {
createPage(workspace!, generateDefaultPageId()).then(page => {
initialPage(page);
setCurrentPage(page);
});
} else {
const page = workspace.getPage(initialPageId);
setCurrentPage(page);
}
}, [workspace, router.query.pageId, setCurrentPage]);
useEffect(() => {
@@ -106,4 +102,4 @@ const InitialEditor = ({
return <div />;
};
export default InitialEditor;
export default EditorReactor;
@@ -0,0 +1,28 @@
import { Page } from '@blocksuite/store';
import { QueryContent } from '@blocksuite/store/dist/workspace/search';
export interface PageMeta {
id: string;
title: string;
favorite: boolean;
trash: boolean;
createDate: number;
trashDate: number | null;
}
export type EditorHandlers = {
createPage: (pageId?: string) => Promise<Page>;
openPage: (
pageId: string,
query?: { [key: string]: string }
) => Promise<boolean>;
getPageMeta: (pageId: string) => PageMeta | void;
deletePage: (pageId: string) => void;
recyclePage: (pageId: string) => void;
toggleDeletePage: (pageId: string) => void;
favoritePage: (pageId: string) => void;
unFavoritePage: (pageId: string) => void;
toggleFavoritePage: (pageId: string) => void;
permanentlyDeletePage: (pageId: string) => void;
search: (query: QueryContent) => any;
};
@@ -0,0 +1,65 @@
import { QueryContent } from '@blocksuite/store/dist/workspace/search';
import { createPage, initialPage, generateDefaultPageId } from './utils';
import { Workspace } from '@blocksuite/store';
import { useRouter } from 'next/router';
import { EditorHandlers } from './interface';
export const useEditorHandler = (workspace?: Workspace): EditorHandlers => {
const router = useRouter();
return {
createPage: async (pageId = generateDefaultPageId()) => {
const page = await createPage(workspace!, pageId);
initialPage(page);
return page;
},
getPageMeta(pageId: string) {
pageId = pageId.replace('space:', '');
return workspace!.meta.pageMetas.find(page => page.id === pageId);
},
openPage: (pageId, query = {}) => {
return router.push({
pathname: '/',
query: {
pageId,
...query,
},
});
},
deletePage: pageId => {
workspace!.setPageMeta(pageId, { trash: true });
},
recyclePage: pageId => {
workspace!.setPageMeta(pageId, { trash: false });
},
toggleDeletePage: pageId => {
const pageMeta = workspace!.meta.pageMetas.find(p => p.id === pageId);
if (pageMeta) {
workspace!.setPageMeta(pageId, { trash: !pageMeta.trash });
}
},
favoritePage: pageId => {
workspace!.setPageMeta(pageId, { favorite: true });
},
permanentlyDeletePage: pageId => {
// TODO: workspace.meta.removePage or workspace.removePage?
workspace!.meta.removePage(pageId);
},
unFavoritePage: pageId => {
workspace!.setPageMeta(pageId, { favorite: true });
},
toggleFavoritePage: pageId => {
const pageMeta = workspace?.meta.pageMetas.find(p => p.id === pageId);
if (pageMeta) {
workspace!.setPageMeta(pageId, { favorite: !pageMeta.favorite });
}
},
search: (query: QueryContent) => {
if (query) {
return workspace!.search(query);
}
},
};
};
export default useEditorHandler;
@@ -1,5 +1,6 @@
import { EditorContainer } from '@blocksuite/editor';
import exampleMarkdown from '@/providers/editor-provider/example-markdown';
import { Page, Workspace } from '@blocksuite/store';
export const initDefaultContent = (editor: EditorContainer) => {
const { page } = editor;
@@ -11,3 +12,27 @@ export const initDefaultContent = (editor: EditorContainer) => {
editor.clipboard.importMarkdown(exampleMarkdown, `${groupId}`);
page.resetHistory();
};
export const createPage = (
workspace: Workspace,
pageId: string
): Promise<Page> => {
return new Promise(resolve => {
workspace.createPage(pageId);
workspace.signals.pageAdded.once(addedPageId => {
const page = workspace!.getPage(addedPageId);
resolve(page);
});
});
};
export const initialPage = (page: Page) => {
const pageBlockId = page.addBlock({ flavour: 'affine:page' });
const groupId = page.addBlock({ flavour: 'affine:group' }, pageBlockId);
page.addBlock({ flavour: 'affine:paragraph' }, groupId);
return page;
};
export const generateDefaultPageId = () => {
return new Date().getTime().toString();
};
+27 -17
View File
@@ -22,10 +22,10 @@ importers:
packages/app:
specifiers:
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/blocks': 0.3.0-alpha.7
'@blocksuite/editor': 0.3.0-alpha.7
'@blocksuite/icons': ^1.0.5
'@blocksuite/store': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.7
'@emotion/css': ^11.10.0
'@emotion/react': ^11.10.4
'@emotion/server': ^11.10.0
@@ -54,10 +54,10 @@ importers:
react-dom: 18.2.0
typescript: 4.8.3
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/blocks': 0.3.0-alpha.7
'@blocksuite/editor': 0.3.0-alpha.7
'@blocksuite/icons': 1.0.5_w5j4k42lgipnm43s3brx6h3c34
'@blocksuite/store': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.7
'@emotion/css': 11.10.0
'@emotion/react': 11.10.4_w5j4k42lgipnm43s3brx6h3c34
'@emotion/server': 11.10.0_@emotion+css@11.10.0
@@ -174,12 +174,14 @@ packages:
to-fast-properties: 2.0.0
dev: false
/@blocksuite/blocks/0.3.0-alpha.6:
resolution: {integrity: sha512-pa8wP0hRIDlufae+ABAQFLW8TNOGsfh8AqyTKF/+LVYFCGr+9tlW55X3OlWtU51vFxawst1Wd3FnjCAW6XiaKQ==}
/@blocksuite/blocks/0.3.0-alpha.7:
resolution: {integrity: sha512-RV6yiKSVIr3hRkT1MYp15Bt7i615aahqQ7CEJZQAuDMr2OVRzAGeXJpjt3e69HWW5os4fs4yOsC1PiS8VuuWRg==}
dependencies:
'@blocksuite/store': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.7
'@tldraw/vec': 1.8.0
hotkeys-js: 3.10.0
lit: 2.4.0
perfect-freehand: 1.2.0
quill: 1.3.7
quill-cursors: 4.0.0
transitivePeerDependencies:
@@ -188,11 +190,11 @@ packages:
- utf-8-validate
dev: false
/@blocksuite/editor/0.3.0-alpha.6:
resolution: {integrity: sha512-2wFkOlCKqC4BrfCIzuxjUyVnE/mmGOyUnqVTQNmHrToDS81RLIq0r+lj1IrzLv+LZQCfTyhoAlJyaxUNrUw3sw==}
/@blocksuite/editor/0.3.0-alpha.7:
resolution: {integrity: sha512-vq5xgg2Ea1kbYDCYogBnmccg3Opw2DfQeiEQM5JRxqRBe6E2R4lZqZvksVj5fekY5Pl2Nrr73VgxTutjGS1u2g==}
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.6
'@blocksuite/blocks': 0.3.0-alpha.7
'@blocksuite/store': 0.3.0-alpha.7
lit: 2.4.0
marked: 4.1.1
turndown: 7.1.1
@@ -212,8 +214,8 @@ packages:
react: 18.2.0
dev: false
/@blocksuite/store/0.3.0-alpha.6:
resolution: {integrity: sha512-rI7cUVSqoMh1bsNLwL8MAgyaUq0Ix+SRBqweYwVjeDoqFIbHjnRSwkVw48K/FgxN6ekN96HLSf3Sj/HK1ivPpw==}
/@blocksuite/store/0.3.0-alpha.7:
resolution: {integrity: sha512-dO+hx/6V5aun5+U1M7qRSQLdHpXYNa2TDr9747f+Xy8CoToyYQ5jTJ/KcjKEdNm36xg66N3sNBDarhAUzs3QOg==}
dependencies:
buffer: 6.0.3
flexsearch: 0.7.21
@@ -1087,6 +1089,10 @@ packages:
tslib: 2.4.0
dev: false
/@tldraw/vec/1.8.0:
resolution: {integrity: sha512-GiS5Df3CzXY/fPBFcM0CKFERZfI4Cg1X33VPZX+NLo7Fwm/h9zu/aU24N1mG75Q9LuMnwKm7woxKr8BiUXGYCg==}
dev: false
/@types/json5/0.0.29:
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
dev: true
@@ -1871,7 +1877,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm
'@typescript-eslint/parser': 5.38.0_eslint@8.22.0
debug: 3.2.7
eslint: 8.22.0
eslint-import-resolver-node: 0.3.6
@@ -1890,7 +1896,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm
'@typescript-eslint/parser': 5.38.0_eslint@8.22.0
array-includes: 3.1.5
array.prototype.flat: 1.3.0
debug: 2.6.9
@@ -3033,6 +3039,10 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
/perfect-freehand/1.2.0:
resolution: {integrity: sha512-h/0ikF1M3phW7CwpZ5MMvKnfpHficWoOEyr//KVNTxV4F6deRK1eYMtHyBKEAKFK0aXIEUK9oBvlF6PNXMDsAw==}
dev: false
/picocolors/1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: false