16 comments

[ 19.7 ms ] story [ 140 ms ] thread
Disclosure: I work on a related project (Fluid Framework) that makes application agnostic CRDTs easily available.

The CKEditor folks did a great job building an OSS text editor and they did an especially strong work building a text editor that works well with collaboration. I've made a few OSS rich text editors work (mostly) with Fluid [0, 1] and the design of the text editor really changes how easily collaboration can be added. Luckily the text editor accepts remote changes, integrating an OT or CRDT solution is approximately the same.

They also did a great job explaining the problem. My experience has been that people don't intuitively understand why real time collaboration is a tricky problem. I didn't. First of all, for a bunch of use cases websockets + redis + a last write wins conflict resolution (or some similar solution) is totally enough. Second, it's not immediately obvious why rich text editing requires more complex conflict resolution. Third, it's not obvious why solving the RTE problem doesn't immediately lend itself to other problems [2].

Because we started building in mid-late 2017, right as CRDTs really started to get competitive with OT, we chose a CRDT approach, but the collab problem space in general is much deeper I realized before getting into it.

Anyway, I always appreciate seeing people explain their journey. Especially when it has to do with collaboration.

[0] https://fluidframework.com/playground/?path=/docs/react-demo... [1] https://github.com/microsoft/FluidFramework/tree/main/exampl... [2] https://www.youtube.com/watch?v=x7drE24geUw

I was thinking about this the other day and realised the rsync algorithm should be feasible to compile to javascript to provide a sporadic, byte-efficient synchronization system with smart polling fallbacks in the case of zero websockets without the need for polling, websockets or JSON-based diffing protocols.
The problem as I've understood it is conflict resolution, not diffing.

Rsync only does one-way sync so it does not help much here.

I guess you can have a distributed locking mechanism, either scope or line-driven.

Another option would be when there is a conflict you have a fork, and then re-merge at a later point (eg. when scope-specific changes are complete or scope is left or syntax is re-evaluated as valid), more similar to git style workflow. Which begs the question, why not just use an established RCS/VCS like git and build the interface in front of it, utilizing its built-in diff? However, this workflow probably detracts greatly from the real time intent...

> I guess you can have a distributed locking mechanism, either scope or line-driven

In real time? How would that solve the problems outlined in the article?

> However, this workflow probably detracts greatly from the real time intent

Seems like you understand the problem.

There's no other way to say this: I dislike ckeditor.

An application I have to use frequently uses it for rich text entry.

But I use firefox + a mac and it seems poorly suited. I don't think safari works either.

It replaces the default editing keys so every time I hit control-b - instead of going back a character I turn on bold. Every time I hit control-k - instead of clearing to end of line, it pops up a create link dialog.

That's very weird - on mac, I'd expect bold and 'create link' to be exactly those shortcuts, but with the apple key replacing control...
ok what
He means (correctly) that on a mac the command for bold is cmd-b instead of control-b (which is bold on windows)
Are those the only complaints with it? Those actions for the shortcuts you mentioned seem pretty standard so it might be worth adjusting to them and figuring out how to work around it in whatever software uses different responses.

You could also look into Karabiner (https://karabiner-elements.pqrs.org/) to create some custom keybindings. I've used it to rebind capslock to act as a modifier so that capslock + 3 = start of line, capslock + 4 = end of line, + hjkl = left, down, up, right, etc. Nice way to get consistent behavior without worrying about what binds a particular piece of software has defined