В Slate. js editor.apply (операция) неправильно применяет операции split_node - PullRequest
5 голосов
/ 12 февраля 2020

Я разрабатываю google-do c инструмент для совместной работы с последним React + Slate в качестве внешнего интерфейса и Flask в Backend. Я использую socket-io в React и flask_socketio в Python для передачи и прослушивания контента от других соавторов. Реагировать код приложения:

const RichTextExample = props => {
  const [value, setValue] = useState(props.currentEditor);
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);
  const id = useRef(`${Date.now()}`);
  const remote = useRef(false);
  const socketchange = useRef(false);

  useEffect(() => {
    socket.on("new-remote-operations", ({ editorId, ops, doc_id }) => {
      if (id.current !== editorId && doc_id === props.document.doc_id) {
        remote.current = true;
        JSON.parse(ops).forEach(op => {
          console.log("LISTEN: applying op", op);
          editor.apply(op);
        });
        remote.current = false;
        console.log('value is ', value);
        socketchange.current = true; //variable to track socket changes in editor via operations
      }
    });}, [])
    return(
    <Slate
        editor={editor}
        value={value}
        onChange={value => {
          setValue(value);
          const ops = editor.operations
          .filter(o => {
            if (o) {
              return o.type !== "set_selection" && o.type !== "set_value";
            }
            return false;
          });
          if (ops.length && !remote.current && !socketchange.current) {
            console.log("EMIT: Editor operations are ", ops);
            socket.emit("new-operations", {
              editorId: id.current,
              ops: JSON.stringify(ops),
              doc_id: props.document.doc_id
            });
          }
          socketchange.current = false;
        }}
      >

Python код для сокета прост:

app = Flask(__name__)
db_name = 'userdoc.db'
app.config['SECRET_KEY'] = 'secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+db_name
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('new-operations', namespace='/')
def operations(data):
    print('operations listened...1/2/3..')
    emit('new-remote-operations', data, broadcast=True, include_self=False)

Выпуск :

Когда split_node передается как тип операции в socket.on (), editor.apply (op) не применяет его так, как предполагается. Пожалуйста помоги мне с этим.

Из-за этого я получаю два следующих случая: Case 1

enter image description here enter image description here

1 Ответ

4 голосов
/ 17 февраля 2020

Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что вы отправляете пакет операций, которые не должны применяться одна за другой.

A split_node операция, подобная той, которую вы генерируете, нажимая enter, будет фактически разделить все вложенные узлы, пока не достигнет листьев, и переместить некоторые узлы вокруг.

Конкретно, split_node - это фактически 2-3 операции, следующие друг за другом, которые не могут применяться исключительно. Например, если вы примените первый, это разделит текстовый узел и в итоге получит два Text с одинаковыми атрибутами. Slate нормализует их и повторно объединит их, как только сможет, что в вашем случае происходит между каждым editor.apply(op).

Я думаю, что решение здесь состоит в том, чтобы просто обернуть все ваши l oop внутрь метод withoutNormalizing. Это позволит Slate нормализовать документ между операциями.

Для Slate <= 0,47 </h3> editor.withoutNormalizing(() => { JSON.parse(ops).forEach(op => { editor.apply(op); }); }) Для Slate> = 0,5

Editor.withoutNormalizing(editor, () => {
  JSON.parse(ops).forEach(op => {
    editor.apply(op);
  });
})
...