Saving step history for playing back/forward document changes

I’m experimenting with a system that should enable users to play changes back and forth in a document, similar to the time slider feature available in etherpad (example with a slider at the top of the page:

What I am currently doing is the following:
With each new step that gets applied, I save the step and an inverted version of the step. Using this data I can easily go back and forth in a document’s history, which is already working nicely.

Now I’m facing a few problems with this approach:
When going through history, the user should not be able to see intermediary steps of a single transform. An example would be selecting multiple paragraphs and wrapping them in a list (Ctrl+Shift+8). An action like this should appear as a single change to the user when going through history. This makes sense as from the user’s perspective only a single action was performed. The undo/redo behaves the same way.

The easiest way to solve this problem would probably be to save groups of steps, which each represent a transform. That way the groups of steps could atomically be applied when going through history. The problem with this solution is that the current protocol for collaboration does not contain any information about the transforms/groups and only contains a flat array of steps.
Handling and persisting the history separated from the normal document collaboration doesn’t sound like a good idea, as all of the syncing logic would need to be performed twice and additionally one would need to ensure that the history is consistent with the current document version (in case of timeouts, errors, etc.).

One idea to allow this kind of functionality would be to transmit an array of arrays of steps in the remote protocol instead of only an array of steps. Each array would then represent a transform, which would enable the server to use this additional information. Maybe there are also other use cases which would profit from this additional information of grouped steps.

Would be great to get some input on this. Maybe there are alternative approaches to this challenge?

1 Like

What the undo history does is treat changes that are sufficiently close together in time as a group. You could add timestamps to your steps when you send them over, and use those. Or do chunking on the client and send information about the amount of steps in a chunk along when sending them to the server.

Thanks for the input! A time based chunking approach should solve the problem, but I would prefer saving the “raw” data and do any optional chunking later on, when the user goes through the document history. That way it would be possible to do fine grained chunking for the past few hours and create bigger and bigger chunks the further you go back in time.
There are also cases when I cache unconfirmed steps from the collab module offline to sync them later, which would make it hard to get the timestamps without changing the way the collab module saves data. It could for example happen that many steps get created over a long time period while offline, which would make all of these steps fall into the same timestamp at the time of syncing.

In my particular case it might be best to create a custom version of the collab module, which saves the chunking information at the time of the transform event. That way I could still easily and directly serialize the collab data when offline. I have the feeling that doing any of this logic outside of the collab module would make things unnecessarily complicated.

It’s probably better to wait for more use cases that need steps to be grouped by transforms, before introducing any additional complexity into the standard collab module.