12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- import { useEffect, useMemo, useRef } from "react";
- import { createEditor } from "slate";
- import { withReact } from "slate-react";
- import * as Y from 'yjs';
- import { withYjs, YjsEditor, slateNodesToInsertDelta } from '@slate-yjs/core';
- import { Delta } from '@slate-yjs/core/dist/model/types';
- import { TextDelta } from '@/appflowy_app/interfaces/document';
- const initialValue = [{
- type: 'paragraph',
- children: [{ text: '' }],
- }];
- export function useBindYjs(delta: TextDelta[], update: (_delta: Delta) => void) {
- const yTextRef = useRef<Y.XmlText>();
- // Create a yjs document and get the shared type
- const sharedType = useMemo(() => {
- const ydoc = new Y.Doc()
- const _sharedType = ydoc.get('content', Y.XmlText) as Y.XmlText;
-
- const insertDelta = slateNodesToInsertDelta(initialValue);
- // Load the initial value into the yjs document
- _sharedType.applyDelta(insertDelta);
- const yText = insertDelta[0].insert as Y.XmlText;
- yTextRef.current = yText;
-
- return _sharedType;
- }, []);
- const editor = useMemo(() => withYjs(withReact(createEditor()), sharedType), []);
- useEffect(() => {
- YjsEditor.connect(editor);
- return () => {
- yTextRef.current = undefined;
- YjsEditor.disconnect(editor);
- }
- }, [editor]);
- useEffect(() => {
- const yText = yTextRef.current;
- if (!yText) return;
- const textEventHandler = (event: Y.YTextEvent) => {
- update(event.changes.delta as Delta);
- }
- yText.applyDelta(delta);
- yText.observe(textEventHandler);
-
- return () => {
- yText.unobserve(textEventHandler);
- }
- }, [delta])
-
- return { editor }
- }
|