diff --git a/packages/client/src/components/document/editor/editor.tsx b/packages/client/src/components/document/editor/editor.tsx index cff39f48..a709124b 100644 --- a/packages/client/src/components/document/editor/editor.tsx +++ b/packages/client/src/components/document/editor/editor.tsx @@ -92,21 +92,28 @@ export const Editor: React.FC = ({ user: currentUser, documentId, author const [mentionUsers, setMentionUsers] = useState([]); useEffect(() => { - const indexdbProvider = getIndexdbProvider(documentId, provider.document); - - indexdbProvider.on('synced', () => { - setStatus('loadCacheSuccess'); - }); - provider.on('status', async ({ status }) => { setStatus(status); }); return () => { destoryProvider(provider, 'EDITOR'); + }; + }, [documentId, provider, authority]); + + useEffect(() => { + if (!authority || !authority.editable) return; + + const indexdbProvider = getIndexdbProvider(documentId, provider.document); + + indexdbProvider.on('synced', () => { + setStatus('loadCacheSuccess'); + }); + + return () => { destoryIndexdbProvider(documentId); }; - }, [documentId, provider]); + }, [documentId, provider, authority]); useEffect(() => { if (!editor) return; diff --git a/packages/client/src/components/template/editor/useEditor.tsx b/packages/client/src/components/template/editor/useEditor.tsx new file mode 100644 index 00000000..eab529f8 --- /dev/null +++ b/packages/client/src/components/template/editor/useEditor.tsx @@ -0,0 +1,35 @@ +import { useState, useEffect, DependencyList } from 'react'; +import { EditorOptions } from '@tiptap/core'; +import { Editor } from '@tiptap/react'; + +function useForceUpdate() { + const [, setValue] = useState(0); + + return () => setValue((value) => value + 1); +} + +export const useEditor = (options: Partial = {}, deps: DependencyList = []) => { + const [editor, setEditor] = useState(null); + const forceUpdate = useForceUpdate(); + + useEffect(() => { + const instance = new Editor(options); + + setEditor(instance); + + // instance.on('transaction', () => { + // requestAnimationFrame(() => { + // requestAnimationFrame(() => { + // console.log('update'); + // forceUpdate(); + // }); + // }); + // }); + + return () => { + instance.destroy(); + }; + }, deps); + + return editor; +}; diff --git a/packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts b/packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts index 93e5a799..e38ae57d 100644 --- a/packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts +++ b/packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts @@ -101,7 +101,8 @@ export const createDecorations = (state, awareness, createCursor) => { export const yCursorPlugin = ( awareness, { cursorBuilder = defaultCursorBuilder, getSelection = (state) => state.selection } = {}, - cursorStateField = 'cursor' + cursorStateField = 'cursor', + isEditable = false ) => new Plugin({ key: yCursorPluginKey, @@ -131,6 +132,8 @@ export const yCursorPlugin = ( } }; const updateCursorInfo = () => { + if (!isEditable) return; + const ystate = ySyncPluginKey.getState(view.state); // @note We make implicit checks when checking for the cursor property const current = awareness.getLocalState() || {}; diff --git a/packages/client/src/tiptap/extensions/collaboration-cursor/index.ts b/packages/client/src/tiptap/extensions/collaboration-cursor/index.ts index 5ccdd3bc..7ab00372 100644 --- a/packages/client/src/tiptap/extensions/collaboration-cursor/index.ts +++ b/packages/client/src/tiptap/extensions/collaboration-cursor/index.ts @@ -165,6 +165,7 @@ export const CollaborationCursor = Extension.create = ({ editor }) => { +const _MenuBar: React.FC<{ editor: Editor }> = ({ editor }) => { + const isEditable = useMemo(() => editor.isEditable, [editor]); + if (!editor) return null; return ( -
+
@@ -109,7 +117,7 @@ export const MenuBar = React.memo(_MenuBar, (prevProps, nextProps) => { return prevProps.editor === nextProps.editor; }); -const _CommentMenuBar: React.FC<{ editor: any }> = ({ editor }) => { +const _CommentMenuBar: React.FC<{ editor: Editor }> = ({ editor }) => { return ( <> diff --git a/packages/client/src/tiptap/react/useEditor.tsx b/packages/client/src/tiptap/react/useEditor.tsx index eab529f8..5e68fdfb 100644 --- a/packages/client/src/tiptap/react/useEditor.tsx +++ b/packages/client/src/tiptap/react/useEditor.tsx @@ -20,7 +20,6 @@ export const useEditor = (options: Partial = {}, deps: Dependency // instance.on('transaction', () => { // requestAnimationFrame(() => { // requestAnimationFrame(() => { - // console.log('update'); // forceUpdate(); // }); // }); diff --git a/packages/client/src/tiptap/views/bubble-menu/bubble-menu-plugin.tsx b/packages/client/src/tiptap/views/bubble-menu/bubble-menu-plugin.tsx index 6007fdc9..964290f9 100644 --- a/packages/client/src/tiptap/views/bubble-menu/bubble-menu-plugin.tsx +++ b/packages/client/src/tiptap/views/bubble-menu/bubble-menu-plugin.tsx @@ -133,7 +133,7 @@ export class BubbleMenuView { trigger: 'manual', placement: 'top', hideOnClick: 'toggle', - ...Object.assign({ zIndex: 99 }, this.tippyOptions), + ...Object.assign({ zIndex: 999 }, this.tippyOptions), }); // maybe we have to hide tippy on its own blur event as well @@ -160,14 +160,16 @@ export class BubbleMenuView { const from = Math.min(...ranges.map((range) => range.$from.pos)); const to = Math.max(...ranges.map((range) => range.$to.pos)); - const shouldShow = this.shouldShow?.({ - editor: this.editor, - view, - state, - oldState, - from, - to, - }); + const shouldShow = + this.editor.isEditable && + this.shouldShow?.({ + editor: this.editor, + view, + state, + oldState, + from, + to, + }); if (!shouldShow) { this.hide();