Closed doodlewind closed 2 years ago
Hi @doodlewind, I implemented this behavior as you suggested (just using a different option name). It's released in Yjs@13.5.32.
new Y.UndoManager(type, { ignoreRemoteMapChanges: true })
Would love to hear your feedback!
Checklist
Related Problem
For now when undoing a YMap key that is overwritten by another user, Yjs intentionally disabled this key from being undone (see https://github.com/yjs/yjs/blob/6403bc2bb5/tests/undo-redo.tests.js#L96 and https://github.com/yjs/yjs/blob/6403bc2bb5/src/structs/Item.js#L160-L164). This may bring unexpected result, for example in an graphics editor, we have two users dragging same element:
We can see in this case, neither A nor B could undo their state change, because the key was overwritten by both of them. But if we use the mental model that always simply apply the reverse operation of a client's previous change, both of the clients should be able to recover to their previous state.
Proposed Solution
Since this behavior was controlled by an
if
block explicitly, we can trivially making it adjustable via an option for UndoManager, whose possible name can beignoreOverwrittenKey: boolean
, withtrue
as its default value.With
ignoreOverwrittenKey
set tofalse
, we can get following behavior:In this case, an undo buffer that doesn't prevent user from undoing would make the user experience more alike with the implementation shared by Figma's blog:
To explain this principle, we can notice that after being redone by A, the state is
left: 300
created by B, instead of theleft: 200
one created by A. This is perfectly expected because we were undoing fromleft: 300
, so redoing back toleft: 300
looks good.We have tweaked the code above for enabling this feature in our forked earlier Yjs version, which works well. Thanks again for this awesome library!
Possible Alternatives
Personally I would suggest using
ignoreOverwrittenKey: false
as default, but this may become a breaking change.Huly®: YJS-279