Merge branch 'develop' into feat/quick-search

This commit is contained in:
JimmFly
2022-12-13 15:18:55 +08:00
6 changed files with 169 additions and 135 deletions
@@ -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();
};