mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-10 13:38:49 +08:00
feat: add lifecycle hook in editor provider
This commit is contained in:
@@ -4,29 +4,28 @@ import type { PropsWithChildren } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import Loading from './loading';
|
||||
import { Page, Workspace } from '@blocksuite/store';
|
||||
import useEditorHandler from './useEditorHandler';
|
||||
import { EditorHandlers, PageMeta } from './interface';
|
||||
import useEditorHandler from './hooks/useEditorHandler';
|
||||
import {
|
||||
EditorHandlers,
|
||||
PageMeta,
|
||||
EditorContextValue,
|
||||
EditorContextProps,
|
||||
} from './interface';
|
||||
import usePropsUpdated from '@/providers/editor-provider/hooks/usePropsUpdated';
|
||||
import useHistoryUpdated from '@/providers/editor-provider/hooks/useHistoryUpdated';
|
||||
|
||||
// Blocksuite has to be imported dynamically since it has a lot of effects
|
||||
const DynamicEditor = dynamic(() => import('./editor-reactor'), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
type EditorContextValue = {
|
||||
mode: EditorContainer['mode'];
|
||||
setMode: (mode: EditorContainer['mode']) => void;
|
||||
currentPage: Page | void;
|
||||
editor: EditorContainer | void;
|
||||
pageList: PageMeta[];
|
||||
} & EditorHandlers;
|
||||
|
||||
type EditorContextProps = PropsWithChildren<{}>;
|
||||
|
||||
export const EditorContext = createContext<EditorContextValue>({
|
||||
mode: 'page',
|
||||
setMode: () => {},
|
||||
pageList: [],
|
||||
currentPage: undefined,
|
||||
page: undefined,
|
||||
onPropsUpdated: () => {},
|
||||
onHistoryUpdated: () => {},
|
||||
editor: undefined,
|
||||
...({} as EditorHandlers),
|
||||
});
|
||||
@@ -37,12 +36,24 @@ export const EditorProvider = ({
|
||||
children,
|
||||
}: PropsWithChildren<EditorContextProps>) => {
|
||||
const [workspace, setWorkspace] = useState<Workspace>();
|
||||
const [currentPage, setCurrentPage] = useState<Page>();
|
||||
const [page, setPage] = useState<Page>();
|
||||
const [pageList, setPageList] = useState<PageMeta[]>([]);
|
||||
const [editor, setEditor] = useState<EditorContainer>();
|
||||
const [mode, setMode] = useState<EditorContainer['mode']>('page');
|
||||
|
||||
const editorHandlers = useEditorHandler(workspace);
|
||||
const onPropsUpdated = usePropsUpdated(editor);
|
||||
const onHistoryUpdated = useHistoryUpdated(page);
|
||||
|
||||
// Modify the updatedDate when history change
|
||||
useEffect(() => {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
onHistoryUpdated(page => {
|
||||
workspace.setPageMeta(page.id, { updatedDate: +new Date() });
|
||||
});
|
||||
}, [workspace, onHistoryUpdated]);
|
||||
|
||||
useEffect(() => {
|
||||
const event = new CustomEvent('affine.switch-mode', { detail: mode });
|
||||
@@ -67,21 +78,23 @@ export const EditorProvider = ({
|
||||
<EditorContext.Provider
|
||||
value={{
|
||||
editor,
|
||||
currentPage,
|
||||
page,
|
||||
mode,
|
||||
setMode,
|
||||
pageList,
|
||||
onHistoryUpdated,
|
||||
onPropsUpdated,
|
||||
...editorHandlers,
|
||||
}}
|
||||
>
|
||||
<DynamicEditor
|
||||
workspace={workspace}
|
||||
currentPage={currentPage}
|
||||
currentPage={page}
|
||||
setEditor={setEditor}
|
||||
setWorkspace={setWorkspace}
|
||||
setCurrentPage={setCurrentPage}
|
||||
setCurrentPage={setPage}
|
||||
/>
|
||||
{workspace && currentPage && editor ? children : <Loading />}
|
||||
{workspace && page && editor ? children : <Loading />}
|
||||
</EditorContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -89,7 +89,7 @@ const EditorReactor = ({
|
||||
|
||||
const savedPageId = workspace.meta.pageMetas[0]?.id;
|
||||
if (savedPageId) {
|
||||
setCurrentPage(workspace.getPage(savedPageId));
|
||||
setCurrentPage(workspace.getPage(savedPageId) as Page);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+9
-5
@@ -1,8 +1,8 @@
|
||||
import { QueryContent } from '@blocksuite/store/dist/workspace/search';
|
||||
import { createPage, initialPage, generateDefaultPageId } from './utils';
|
||||
import { createPage, initialPage, generateDefaultPageId } from '../utils';
|
||||
import { Workspace } from '@blocksuite/store';
|
||||
import { useRouter } from 'next/router';
|
||||
import { EditorHandlers } from './interface';
|
||||
import { EditorHandlers, PageMeta } from '../interface';
|
||||
|
||||
export const useEditorHandler = (workspace?: Workspace): EditorHandlers => {
|
||||
const router = useRouter();
|
||||
@@ -15,7 +15,9 @@ export const useEditorHandler = (workspace?: Workspace): EditorHandlers => {
|
||||
},
|
||||
getPageMeta(pageId: string) {
|
||||
pageId = pageId.replace('space:', '');
|
||||
return workspace!.meta.pageMetas.find(page => page.id === pageId);
|
||||
return workspace!.meta.pageMetas.find(
|
||||
page => page.id === pageId
|
||||
) as PageMeta;
|
||||
},
|
||||
openPage: (pageId, query = {}) => {
|
||||
return router.push({
|
||||
@@ -29,8 +31,10 @@ export const useEditorHandler = (workspace?: Workspace): EditorHandlers => {
|
||||
toggleDeletePage: pageId => {
|
||||
const pageMeta = workspace!.meta.pageMetas.find(p => p.id === pageId);
|
||||
if (pageMeta) {
|
||||
workspace!.meta.setPage(pageId, { trashDate: new Date().getTime() });
|
||||
workspace!.setPageMeta(pageId, { trash: !pageMeta.trash });
|
||||
workspace!.setPageMeta(pageId, {
|
||||
trash: !pageMeta.trash,
|
||||
trashDate: +new Date(),
|
||||
});
|
||||
}
|
||||
},
|
||||
favoritePage: pageId => {
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Page } from '@blocksuite/store';
|
||||
import { EventCallBack } from '../interface';
|
||||
|
||||
export type UseHistoryUpdated = (page?: Page) => EventCallBack<Page>;
|
||||
|
||||
export const useHistoryUpdate: UseHistoryUpdated = page => {
|
||||
const callbackQueue = useRef<((page: Page) => void)[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
page.signals.historyUpdated.on(() => {
|
||||
callbackQueue.current.forEach(callback => {
|
||||
callback(page);
|
||||
});
|
||||
});
|
||||
}, 300);
|
||||
|
||||
return () => {
|
||||
callbackQueue.current = [];
|
||||
page.signals.historyUpdated.dispose();
|
||||
};
|
||||
}, [page]);
|
||||
|
||||
return callback => {
|
||||
callbackQueue.current.push(callback);
|
||||
};
|
||||
};
|
||||
|
||||
export default useHistoryUpdate;
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { EditorContainer } from '@blocksuite/editor';
|
||||
import { EventCallBack } from '../interface';
|
||||
|
||||
export type UsePropsUpdated = (
|
||||
editor?: EditorContainer
|
||||
) => EventCallBack<EditorContainer>;
|
||||
|
||||
export const usePropsUpdated: UsePropsUpdated = editor => {
|
||||
const callbackQueue = useRef<((editor: EditorContainer) => void)[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editor?.model) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
editor.model?.propsUpdated.on(() => {
|
||||
callbackQueue.current.forEach(callback => {
|
||||
callback(editor);
|
||||
});
|
||||
});
|
||||
}, 300);
|
||||
|
||||
return () => {
|
||||
callbackQueue.current = [];
|
||||
editor?.model?.propsUpdated.dispose();
|
||||
};
|
||||
}, [editor]);
|
||||
|
||||
return callback => {
|
||||
callbackQueue.current.push(callback);
|
||||
};
|
||||
};
|
||||
|
||||
export default usePropsUpdated;
|
||||
@@ -1,14 +1,28 @@
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { Page } from '@blocksuite/store';
|
||||
import { QueryContent } from '@blocksuite/store/dist/workspace/search';
|
||||
import { PageMeta as OriginalPageMeta } from '@blocksuite/store';
|
||||
import { EditorContainer } from '@blocksuite/editor';
|
||||
|
||||
export interface PageMeta {
|
||||
id: string;
|
||||
title: string;
|
||||
export type EventCallBack<T> = (callback: (props: T) => void) => void;
|
||||
export type EditorContextProps = PropsWithChildren<{}>;
|
||||
|
||||
export type EditorContextValue = {
|
||||
mode: EditorContainer['mode'];
|
||||
setMode: (mode: EditorContainer['mode']) => void;
|
||||
page: Page | void;
|
||||
editor: EditorContainer | void;
|
||||
pageList: PageMeta[];
|
||||
onHistoryUpdated: EventCallBack<Page>;
|
||||
onPropsUpdated: EventCallBack<EditorContainer>;
|
||||
} & EditorHandlers;
|
||||
|
||||
export type PageMeta = {
|
||||
favorite: boolean;
|
||||
trash: boolean;
|
||||
createDate: number;
|
||||
trashDate: number | null;
|
||||
}
|
||||
trashDate: number | void;
|
||||
updatedDate: number | void;
|
||||
} & OriginalPageMeta;
|
||||
|
||||
export type EditorHandlers = {
|
||||
createPage: (pageId?: string) => Promise<Page>;
|
||||
|
||||
Reference in New Issue
Block a user