We're building a new multiplayer editor for tasks/notes [1] which supports both text and outliner operations. Although it behaves like a flat text document, the outliner features essentially turn the document into a large tree under the hood. We do something similar to the highly-available move operation to sync changes:
There is one operation to change the tree, called insmov (move-or-insert). Whenever a client is online it can sync changes C to a server. Whenever the server has remote changes for us, it will send us back a list R of all changes since our last sync in a global linear order. We then undo any of the insmovs in our changeset C, and (re)apply all changes in R + any new changes we didn't sync yet.
We don't use any fractional indices though. Instead, our insmov tuple not only contains a parent P, but also a previous sibling guid A. Because all tree ops will eventually be applied in the global linear order as determined by the server, "sorting" is handled by just using the insmov operation.
Most of the time the undo'ing of operations is not needed though. Only when the server has insmov changes we don't know about while we are sending new insmovs ourselves do we need to ensure we replay the operations in the correct order. That's likely to happen when you reconnect to wifi after a long flight, but not so likely when updates are pushed in real-time over websocket when you're online (plus it's not needed for non-insmov operations, like updating text).
what rich text are you using?
We built it from scratch, so not based on prosemirror or contenteditable or anything like that (as we needed something which feels as if you're just editing text but also supports outlining features)
Does it to RTL and vertical text? Full Unicode?
very cool! can't wait to try I'm doing a note editor as well, and would love to have great outlining support!
For what it's worth, this sounds equivalent to the RGA list CRDT [1], using the server's global linear order as a logical timestamp (in place of e.g. Lamport timestamps).
[1] https://inria.hal.science/inria-00555588/
Right but rather than working on an array it's combined with a tree operation in this case, so if someone drags a task to reorder but someone else moves it to another parent it won't cause (cycle) conflicts
Hey wim! Coincidentally yesterday I was reading an old thread[0] and saw your post about thymer which got me curious. When I searched on HN for thymer I got a show hn in 2009[1] and it seems Thymer is in private beta for the past 15 years?
0. https://news.ycombinator.com/item?id=40786425
1. https://news.ycombinator.com/item?id=518803
Hah well there is definitely some scope/vision creep involved, and it all took a bit longer than planned. Not 15 years though! (that's about the very first app we ever made, which we only keep online for existing users). We've been working on this new project as a team of 2 for almost three years now. We really wanted to get it right so we spent a lot of time building the editor/IDE completely from scratch, as well as all the other stuff like the syncing layer (which is how I became interested in the topic of CRDTs and such).