Этот день всё-таки пришел. Мы выкатили обновленную версию редакторов документов ONLYOFFICE Document Editors 3.6 с быстрым совместным редактированием, как в Google Docs. Его давно просили, требовали, угрожали, но мы были неумолимы. До тех пор, пока не сдались под напором пользователей, желающих редактировать свои секретные материалы, в режиме реального времени наблюдая, что набирает соавтор.
Далее расскажем, почему мы так противились «быстрому» совместному редактированию, чем наш вариант отличается от похожего режима в других онлайн-редакторах и как мы собираемся решать вопрос undo/redo.
![](https://habrastorage.org/r/w1560/files/20b/894/c56/20b894c566804a2f8cbe704612381790.png)
Когда мы выбирали, как именно будет реализована совместная работа с документами в наших редакторах, у нас не было никаких сомнений в том, что «строгий» режим — лучший вариант. Работая таким образом, пользователь видит правки соавтора только после того, как тот сохранит изменения.
Именно при таком режиме редактирования пользователи могут одновременно править многостраничный документ, не мешая друг другу. То есть, правки пользователя, редактирующего документ на первой странице, не создадут никаких неудобств для его соавтора, работающего на 20-ой. В случае «быстрого» редактирования первый мог бы помешать второму, так как его изменения запускают пересчет страниц документа. Кроме того, если пользователи пишут что-то на разных страницах, им и не нужно знать об изменениях, произошедших буквально на другом конце документа.
Другие аргументы в пользу «строгого» режима редактирования:
В целом, такой подход казался нам более продуктивным и универсальным, поэтому классический режим совместного редактирования в ONLYOFFICE именно «строгий». Подробнее о нем можно узнать в нашем стареньком, но не потерявшем актуальности тексте.
Мы не комплексовали по поводу отсутствия быстрого режима совместного редактирования, однако пользователи хотели его. Как и наш отдел PR, практикующий совместное творчество в режиме real-time. В общем, мы сдались и даже нашли
Плюсы «быстрого» режима:
В новой версии редакторов «быстрый» режим совместного редактирования установлен по умолчанию. Вернуть классический «Строгий» можно, следуя несложной схеме: меню «Файл» — вкладка «Дополнительные параметры» — «Co-editing mode». Переключаться между режимами можно в любое время.
При «строгом» редактировании происходит «зажатие» фрагмента документа, над которым работает пользователь. Для его соавторов объект заблокирован до тех пор, пока пользователь не сохранит свои изменения. После сохранения объект разблокируется, пока кто-то вновь не примется неистово его редактировать. При «строгом» редактировании пользователь сохраняет свои правки руками. Кроме того, раз в десять минут происходит автосохранение документа.
При «быстром» редактировании механизм работы, по сути, не меняется. За исключением того, что автосохранение происходит чаще. 25 раз в секунду таймер запрашивает наличие изменений и, если они были внесены, делает save. Сразу после сохранения объект разблокируется. Таким образом, создается ощущение, что редактируемый фрагмент даже не был заблокирован. На самом деле, lock существовал лишь 1/25 секунды и, если в нашем редакторе не набирает текст Флэш, то, в общем, эту маленькую хитрость никто не заметит.
Схема с зажатием оказалась практически идеальной для всего, кроме набора и удаления текста. В этих случаях блокирование параграфа, даже самое непродолжительное, вызывало неприятные природные явления: некоторые буквы просто не набирались. Поэтому от блокировки параграфов при вводе и удалении текста нам пришлось отказаться (в остальных случаях блокировка по-прежнему присутствует).
Далее нам нужно было обеспечить одновременный ввод/удаление текста из одного параграфа для нескольких пользователей. Для этого нам потребовался алгоритм преобразования изменений, или, как его еще называют, операциональное преобразование. На самом деле, этот алгоритм уже существовал в нашем редакторе. В «строгом» режиме редактирования он отвечал за слияние добавленных/удаленных параграфов в документе. Хотя на момент разработки мы даже не знали о том, что «придумываем» операциональное преобразование.
Суть алгоритма в следующем:
Допустим, у нас есть параграф с текстом «авбр» и два пользователя — Номер Один и Номер Два, которые хотят одновременно внести изменения в данный текст. Например, Номер Один вводит в начало слова букву «х», а Номер Два удаляет букву «в». При слиянии должно получится «хабр».
![](https://habrastorage.org/r/w1560/files/cdd/11e/7d4/cdd11e7d4a9b4a98b65ea9c9b83a1e87.png)
Для алгоритма действия пользователей можно записать как ins(«x», 0) (вставка буквы «x» в нулевую позицию) и del(1) (удаление в позиции 1). Попробуем последовательно выполнить эти преобразования с учетом того, чьи изменения первыми придут на сервер:
![](https://habrastorage.org/r/w1560/files/472/d4f/43b/472d4f43bf704abeaf4fc33774de0646.png)
Видно, что сложность заключается не только в самих изменениях, но и в том, кто из пользователей успел отправить свои правки первым. Решение данной проблемы в том, что изменения пользователя, которые приходят на сервер вторыми, нужно преобразовывать через изменения, которые пришли первыми. В первом случае, поскольку удаление в позиции 1 не меняет вставку в позиции 0, второе изменение не меняется.
Во втором случае вставка в позицию 0 влияет на последующее удаление в позиции 1, оно преобразуется в удаление в позиции 2. В итоге после преобразования мы получаем следующую схему.
![](https://habrastorage.org/r/w1560/files/c1f/385/23f/c1f38523ff664ac89e36e9ed38447cb9.png)
По такому принципу работают все текстовые (и не только текстовые) редакторы, у которых есть совместное редактирование в онлайне. Впрочем, наш вариант несколько отличается от того, как всё устроено в других онлайн-редакторах.
Разница в том, где происходит преобразование отправленных изменений. У остальных онлайн-редакторов (например, Google Docs) ответственным за процессы преобразования является сервер. Изменения приходят к нему в нетронутом виде: в нашем случае это ins(«x», 0) от Номера Один и del(1) от Номера Два. Далее сервер преобразует полученные правки и отправляет их пользователям. Таким образом, Номер Один получит del(2), а Номер Два - ins(«x», 0).
![](https://habrastorage.org/r/w1560/files/3be/85c/5ca/3be85c5ca6fc4c5abd373114f74da6a4.png)
В нашей схеме все произойдет по-другому. Оба пользователя отправят на сервер запрос на сохранение своих изменений. Один из них получит ответ «можно», а второй «нельзя». Тот, которому пришло «можно», сразу отправит свои изменения на сервер, который, в свою очередь, перешлет их второму пользователю. Второй пользователь применит эти изменения и (по описанной выше схеме) преобразует через них свои. Только после этого он отправит свои преобразованные изменения на сервер. Затем правки придут первому пользователю.
![](https://habrastorage.org/r/w1560/files/c46/d03/e60/c46d03e60ff54f0eb0a44fa0685919c6.png)
Главный плюс нашей схемы в том, что мы не загружаем сервер — на нем хранится только список изменений, которые были произведены с документом, и организуется очередь сохранения.
Сразу признаем, у нас пока нет undo в режиме «быстрого» совместного редактирования. К сожалению, такого undo, какой хотели бы пользователи, нет ни у кого.
Например, undo редакторов Google Docs работает частично. Он, скорее, рассчитан на то, что пользователи будут отменять мелкие оплошности, опечатки. Попытки откатить более серьезные изменения могут привести к непредсказуемым последствиям.
Допустим, один человек добавил таблицу, а другой начал её менять, скажем, двигать границы, вводить текст. Затем первый решил сделать undo добавления таблицы. По сути таблица пропадет со всем, что сделал в ней второй пользователь. Если он, например, перетащил в таблицу часть текста из документа, то она канет в небытие вместе с отмененной таблицей. Кроме того, для такого варианта undo невозможно сделать правильное redo с точки зрения внесенных в документ изменений.
Схема undo/redo в Google Docs не возвращает документ в исходный вид, как этого хотел бы пользователь, напротив — может сделать его таким, каким этот документ никогда не был.
Нам больше импонирует вариант, придуманный компанией Microsoft: пользователь вносит свои правки и может откатывать их сколько угодно, но только до тех пор, пока к редактированию не подключится пользователь номер два и не внесет свои правки. Затем undo будет работать у второго пользователя. Пока не появится третий. Этот вариант кажется нам правильным с точки зрения редактирования, поэтому сейчас мы работаем над реализацией этой схемы в наших редакторах.
Впрочем, мы думаем и над добавлением undo, которое работало бы примерно как у Google. В наших планах оно мирно сосуществует с вариантом Microsoft: пока можно делать корректное undo/redo, мы делаем его, затем пробуем делать undo как в Google Docs.
Возможность переключения режимов редактирования — это наше нововведение. Пользователи, одновременно работающие с документом, могут выбрать наиболее комфортный для себя способ редактирования.
Например, у Номера Один включен «строгий» режим, а у Номера Два — «быстрый». Первый блокирует объекты и сохраняет свои изменения сам. Второй ничего не блокирует, а сохранение у него происходит автоматически. Если первый редактирует объект или фрагмент текста, второй ничего не может в них делать. При этом первый не видит, что делает второй — пусть будет сюрприз. После сохранения Номер Один отправит свои изменения и примет изменения Номера Второго.
Если подключается Номер Три с «быстрым» режимом, то они с Номером Вторым спокойно работают в режиме быстрого совместного редактирования. При этом они не видят и не могут править то, что заблокировал тот самый интроверт Номер Один. У последнего, кстати, работают и undo, и redo.
Такая схема работы кажется нам логичной и удобной — она позволяет пользователям выбирать способ взаимодействия с соавторами в зависимости от поставленных задач и настроения. Переключение между режимами возможно в любой момент редактирования.
Попробовать быстрое совместное редактирование в действии можно здесь.
P.S. В новой версии редакторов ONLYOFFICE также появился режим рецензирования с отслеживанием изменений, внесенных в ходе проверки документа. Предложенные правки можно принять или отклонить.
P.P.S. Работа над редакторами не прекращается вообще никогда. Мы всё время думаем, что бы такое добавить и улучшить. Поэтому впереди еще много всего.
Далее расскажем, почему мы так противились «быстрому» совместному редактированию, чем наш вариант отличается от похожего режима в других онлайн-редакторах и как мы собираемся решать вопрос undo/redo.
![](https://habrastorage.org/files/20b/894/c56/20b894c566804a2f8cbe704612381790.png)
Строгий vs быстрый
Когда мы выбирали, как именно будет реализована совместная работа с документами в наших редакторах, у нас не было никаких сомнений в том, что «строгий» режим — лучший вариант. Работая таким образом, пользователь видит правки соавтора только после того, как тот сохранит изменения.
Именно при таком режиме редактирования пользователи могут одновременно править многостраничный документ, не мешая друг другу. То есть, правки пользователя, редактирующего документ на первой странице, не создадут никаких неудобств для его соавтора, работающего на 20-ой. В случае «быстрого» редактирования первый мог бы помешать второму, так как его изменения запускают пересчет страниц документа. Кроме того, если пользователи пишут что-то на разных страницах, им и не нужно знать об изменениях, произошедших буквально на другом конце документа.
Другие аргументы в пользу «строгого» режима редактирования:
- Отсутствие отвлекающих факторов в виде комментариев коллег относительно внесенных изменений и их собственных правок;
- Отсутствие конфликтов с undo/redo;
- И, конечно же, возможность поправить грамматические и пунктуационные ошибки, до того как коллеги разразятся вихрем шуточек по этому поводу.
В целом, такой подход казался нам более продуктивным и универсальным, поэтому классический режим совместного редактирования в ONLYOFFICE именно «строгий». Подробнее о нем можно узнать в нашем стареньком, но не потерявшем актуальности тексте.
Мы не комплексовали по поводу отсутствия быстрого режима совместного редактирования, однако пользователи хотели его. Как и наш отдел PR, практикующий совместное творчество в режиме real-time. В общем, мы сдались и даже нашли
Плюсы «быстрого» режима:
- Удобство и скорость при работе с небольшими документами (несколько страниц);
- Зрелищность;
- Удобство для совместной разработки идеи, например, мозгового штурма;
- Возможность оперативно внести и отследить финальные правки при совместной работе над итоговой версией документа.
В новой версии редакторов «быстрый» режим совместного редактирования установлен по умолчанию. Вернуть классический «Строгий» можно, следуя несложной схеме: меню «Файл» — вкладка «Дополнительные параметры» — «Co-editing mode». Переключаться между режимами можно в любое время.
Как всё устроено
При «строгом» редактировании происходит «зажатие» фрагмента документа, над которым работает пользователь. Для его соавторов объект заблокирован до тех пор, пока пользователь не сохранит свои изменения. После сохранения объект разблокируется, пока кто-то вновь не примется неистово его редактировать. При «строгом» редактировании пользователь сохраняет свои правки руками. Кроме того, раз в десять минут происходит автосохранение документа.
При «быстром» редактировании механизм работы, по сути, не меняется. За исключением того, что автосохранение происходит чаще. 25 раз в секунду таймер запрашивает наличие изменений и, если они были внесены, делает save. Сразу после сохранения объект разблокируется. Таким образом, создается ощущение, что редактируемый фрагмент даже не был заблокирован. На самом деле, lock существовал лишь 1/25 секунды и, если в нашем редакторе не набирает текст Флэш, то, в общем, эту маленькую хитрость никто не заметит.
Операциональное преобразование
Схема с зажатием оказалась практически идеальной для всего, кроме набора и удаления текста. В этих случаях блокирование параграфа, даже самое непродолжительное, вызывало неприятные природные явления: некоторые буквы просто не набирались. Поэтому от блокировки параграфов при вводе и удалении текста нам пришлось отказаться (в остальных случаях блокировка по-прежнему присутствует).
Далее нам нужно было обеспечить одновременный ввод/удаление текста из одного параграфа для нескольких пользователей. Для этого нам потребовался алгоритм преобразования изменений, или, как его еще называют, операциональное преобразование. На самом деле, этот алгоритм уже существовал в нашем редакторе. В «строгом» режиме редактирования он отвечал за слияние добавленных/удаленных параграфов в документе. Хотя на момент разработки мы даже не знали о том, что «придумываем» операциональное преобразование.
Суть алгоритма в следующем:
Допустим, у нас есть параграф с текстом «авбр» и два пользователя — Номер Один и Номер Два, которые хотят одновременно внести изменения в данный текст. Например, Номер Один вводит в начало слова букву «х», а Номер Два удаляет букву «в». При слиянии должно получится «хабр».
![](https://habrastorage.org/files/cdd/11e/7d4/cdd11e7d4a9b4a98b65ea9c9b83a1e87.png)
Для алгоритма действия пользователей можно записать как ins(«x», 0) (вставка буквы «x» в нулевую позицию) и del(1) (удаление в позиции 1). Попробуем последовательно выполнить эти преобразования с учетом того, чьи изменения первыми придут на сервер:
![](https://habrastorage.org/files/472/d4f/43b/472d4f43bf704abeaf4fc33774de0646.png)
Видно, что сложность заключается не только в самих изменениях, но и в том, кто из пользователей успел отправить свои правки первым. Решение данной проблемы в том, что изменения пользователя, которые приходят на сервер вторыми, нужно преобразовывать через изменения, которые пришли первыми. В первом случае, поскольку удаление в позиции 1 не меняет вставку в позиции 0, второе изменение не меняется.
Во втором случае вставка в позицию 0 влияет на последующее удаление в позиции 1, оно преобразуется в удаление в позиции 2. В итоге после преобразования мы получаем следующую схему.
![](https://habrastorage.org/files/c1f/385/23f/c1f38523ff664ac89e36e9ed38447cb9.png)
По такому принципу работают все текстовые (и не только текстовые) редакторы, у которых есть совместное редактирование в онлайне. Впрочем, наш вариант несколько отличается от того, как всё устроено в других онлайн-редакторах.
Главное отличие
Разница в том, где происходит преобразование отправленных изменений. У остальных онлайн-редакторов (например, Google Docs) ответственным за процессы преобразования является сервер. Изменения приходят к нему в нетронутом виде: в нашем случае это ins(«x», 0) от Номера Один и del(1) от Номера Два. Далее сервер преобразует полученные правки и отправляет их пользователям. Таким образом, Номер Один получит del(2), а Номер Два - ins(«x», 0).
![](https://habrastorage.org/files/3be/85c/5ca/3be85c5ca6fc4c5abd373114f74da6a4.png)
В нашей схеме все произойдет по-другому. Оба пользователя отправят на сервер запрос на сохранение своих изменений. Один из них получит ответ «можно», а второй «нельзя». Тот, которому пришло «можно», сразу отправит свои изменения на сервер, который, в свою очередь, перешлет их второму пользователю. Второй пользователь применит эти изменения и (по описанной выше схеме) преобразует через них свои. Только после этого он отправит свои преобразованные изменения на сервер. Затем правки придут первому пользователю.
![](https://habrastorage.org/files/c46/d03/e60/c46d03e60ff54f0eb0a44fa0685919c6.png)
Главный плюс нашей схемы в том, что мы не загружаем сервер — на нем хранится только список изменений, которые были произведены с документом, и организуется очередь сохранения.
Отменить/вернуть
Сразу признаем, у нас пока нет undo в режиме «быстрого» совместного редактирования. К сожалению, такого undo, какой хотели бы пользователи, нет ни у кого.
Например, undo редакторов Google Docs работает частично. Он, скорее, рассчитан на то, что пользователи будут отменять мелкие оплошности, опечатки. Попытки откатить более серьезные изменения могут привести к непредсказуемым последствиям.
Допустим, один человек добавил таблицу, а другой начал её менять, скажем, двигать границы, вводить текст. Затем первый решил сделать undo добавления таблицы. По сути таблица пропадет со всем, что сделал в ней второй пользователь. Если он, например, перетащил в таблицу часть текста из документа, то она канет в небытие вместе с отмененной таблицей. Кроме того, для такого варианта undo невозможно сделать правильное redo с точки зрения внесенных в документ изменений.
Схема undo/redo в Google Docs не возвращает документ в исходный вид, как этого хотел бы пользователь, напротив — может сделать его таким, каким этот документ никогда не был.
Нам больше импонирует вариант, придуманный компанией Microsoft: пользователь вносит свои правки и может откатывать их сколько угодно, но только до тех пор, пока к редактированию не подключится пользователь номер два и не внесет свои правки. Затем undo будет работать у второго пользователя. Пока не появится третий. Этот вариант кажется нам правильным с точки зрения редактирования, поэтому сейчас мы работаем над реализацией этой схемы в наших редакторах.
Впрочем, мы думаем и над добавлением undo, которое работало бы примерно как у Google. В наших планах оно мирно сосуществует с вариантом Microsoft: пока можно делать корректное undo/redo, мы делаем его, затем пробуем делать undo как в Google Docs.
В разных режимах
Возможность переключения режимов редактирования — это наше нововведение. Пользователи, одновременно работающие с документом, могут выбрать наиболее комфортный для себя способ редактирования.
Например, у Номера Один включен «строгий» режим, а у Номера Два — «быстрый». Первый блокирует объекты и сохраняет свои изменения сам. Второй ничего не блокирует, а сохранение у него происходит автоматически. Если первый редактирует объект или фрагмент текста, второй ничего не может в них делать. При этом первый не видит, что делает второй — пусть будет сюрприз. После сохранения Номер Один отправит свои изменения и примет изменения Номера Второго.
Если подключается Номер Три с «быстрым» режимом, то они с Номером Вторым спокойно работают в режиме быстрого совместного редактирования. При этом они не видят и не могут править то, что заблокировал тот самый интроверт Номер Один. У последнего, кстати, работают и undo, и redo.
Такая схема работы кажется нам логичной и удобной — она позволяет пользователям выбирать способ взаимодействия с соавторами в зависимости от поставленных задач и настроения. Переключение между режимами возможно в любой момент редактирования.
Попробовать быстрое совместное редактирование в действии можно здесь.
P.S. В новой версии редакторов ONLYOFFICE также появился режим рецензирования с отслеживанием изменений, внесенных в ходе проверки документа. Предложенные правки можно принять или отклонить.
P.P.S. Работа над редакторами не прекращается вообще никогда. Мы всё время думаем, что бы такое добавить и улучшить. Поэтому впереди еще много всего.