-
Notifications
You must be signed in to change notification settings - Fork 39
Description
The problem: inputType historyUndo/historyRedo unusable for editors that maintain their own document state
I was excited to learn that I'm now able to intercept historyUndo and historyRedo inputTypes at beforeinput stage.
But unfortunately I can't utilize them because they are only fired when there are items on the browser-native undo/redo stacks. 😢
Here's a scenario from Svedit:
- user enters a character (I handle this at beforeinput and add a character to my internal model, which triggers a rerender and updates them DOM)
- now i go to Edit > Undo in the browser
- nothing happens because the browser didn't get a history event, as there's nothing on the browser-native undo stack (because I handled everything myself)
There's no way for me to "fake native history entries" as I would always need to let some input slip through and mess with the DOM in order to be recognized as a change that gets added to the native undo history.
I see two directions to solve the problem:
- historyUndo/historyRedo could be triggered always (even though the browser undo stack is empty, so they are more like an "historyUndoRequested" input). Then I get the chance to handle this in my model and run undo (because there I know there's a change that can be undone).
- Only when I don't handle historyUndo/historyRedo (+ call preventDefault) the browser's native undo would run (e.g. when I'm in a text area outside of the contenteditable)
- Programmatic access to create "custom history entries" in the browser programmatically. This means that basically each time I apply a transaction in my model, i can call an API ala document.addHistoryEntry(), without a payload, just to keep the native history stack in sync with my app-specific one. Now I could handle the native
historyUndo/historyRedoalso for my custom history entries. If not handled, they'd result in a no-op. However I may also sometimes call undo/redo programmatically (undo/redo buttons in a toolbar), which would then just work withdocument.executeCommand('undo|redo')I guess?
Without having had a deep reflection on this, my gut says the first option is enough (and more straightforward). Though the second option would allow a more deep integration for custom apps with an undo/redo stack (those app may not even use contenteditable).
A lot of webtools suffer from that issue. E.g. when you edit a file in figma.com, and you use the native "Edit > Undo" nothing happens. You have to use the keybindings, or the menu Figma renders in the browser.