texera icon indicating copy to clipboard operation
texera copied to clipboard

Collating events in the Undo-Redo service

Open MysteriousChallenger opened this issue 3 years ago • 3 comments

The Problem

Here is a TODO that was written ~ 3 years ago when the Undo-Redo service was first created

2. See if there's a way to only store a previous version of an operator's properties
after a certain period of time so we don't undo one character at a time */

The context of this issue is that for every user action, we place a Command object into a "history" list, allowing us to undo and redo/replay all the actions a user has done.

However, This one-action = one-undo rule, while convenient to program, doesn't always make the most sense for the end-user. As the above comment describes, if each keystroke is its own event, one would have to click the undo button once per character, which is greatly annoying.

The Cure

The solution is (in my opinion) to Collate Related Events Together. All those keystroke events in the above example should be grouped in some way, shape, or form, so that they can be undone in one click rather than one character at a time.

Repeated, similar actions of all kinds would make more sense collated: adding many operators at once, deleting many operators at once, closing/opening many operator-groups at once, etc, could all be undone and redone as one.

Implementation Ideas That You Can Ignore If You Want

You may have noticed that the typing issue referenced above has been fixed (although the todo note still exists) This was done inside the operator-property-editor component by using RXJS's debounce feature: the Command representing any previously typed characters would only be emitted after no characters had been typed for a certain period.

This works pretty well for typing, but here are some reasons to make this same Collating feature available at a more abstract level to all Commands

  1. User actions that add a Command to the history may also trigger an arbitrary number of event listeners. Those listeners may also cause actions that could themselves warrant a Command being added to the history. Under our current implementation, this means one user action may require more than one click to undo. All those Commands should be collated as one
  2. My ideal implementation would emit events on the "leading edge" of the signal: That is to say, when a user action is registered, immediately emit the appropriate Command and let all subsequent event listeners collate/glue their commands to the first one. This is the opposite of how typing keystrokes are currently collated, as all the keystroke events wait until the last keystroke to be bundled up as a single Command. I think most people would agree that thinking about asynchronous code is hard, and that events-on-the-leading-edge makes the undo-redo history more synchronous and easy to think about.

MysteriousChallenger avatar Oct 15 '21 17:10 MysteriousChallenger

group discussion 1/13: @zuozhiw will discuss this issue with @MysteriousChallenger

zuozhiw avatar Jan 13 '22 22:01 zuozhiw

We should also take this chance to add framework for future multi-user collab. I.E non-linear undo. With multiple users, the order/history of events may be reshuffled during undo. Sort of like git rebase?

MysteriousChallenger avatar Feb 04 '22 06:02 MysteriousChallenger

Discussion 2022.05.12: WIP. Will come back after shared editing.

Xiao-zhen-Liu avatar May 12 '22 20:05 Xiao-zhen-Liu

Discussion 2022.05.12: Not needed after shared editing.

Xiao-zhen-Liu avatar Dec 08 '22 00:12 Xiao-zhen-Liu