Thanks for your answer Martin!
Nystrom's "Game Patterns" is one of my favourites, but unfortunately doesn't help here. Applications live and die by how good their user interaction is. Anyone writing a modern Laravel web app must deal with some kind of interaction libraries - i.e. Inertia, Livewire, Vue, etc. Because undo and redo are purely interaction features, it means we have to deal with them in the context of these libraries too.
I know how to implement undo and redo in a pure SPA where the whole application is in the front end. What I am stumbling on is the mixture of Laravel (backend) + Vue/Inertia/LiveWire/whatever (frontend) + Laravel or Inertia routing. The division of undo/redo logic and state among all these parts eludes me.
Let's say I'm doing a ToDo App with the usual CRUD operations plus undo/redo for the last 50 changes.
Nobody likes a full page refresh every time a ToDo is marked as done, so there has to be some kind of rich frontend (Vue/React/LiveWire/whatever) that sends requests to the Laravel backend.
Whenever users want to undo/redo, it takes too long to go ask the server "hey what was the last thing the user did?" and wait for the answer. That means the front-end has to remember at least some undo history.
You also don't want to reload the whole page from the server upon "undo", because 1) the user gets confused, 2) there is some UI state that can't/shouldn't be saved on the server. For example: which field of a ToDo was focused, where was the page scroll, which tab in a tab-view is selected, etc. So we have back-end state (the todos + the session) AND front-end state (the todos and other UI-specific state). Which of them is the authoritative state? Is the undo/redo history part of the frontend state or backend state?
The frontend and backend states need to be kept in sync. How?
Let's say the user finishes editing a ToDo in single-view and is taken to the list-view of all ToDos. (This is a different Vue component). The user now remembers "Oops, I edited the wrong ToDo" and presses ctrl-z to undo. For the user's mental concept, "undo" means go back to the previous view as well, i.e. to the single-todo view. How do we know which view and which component was used for the action that was just "undone"? Where do we save this component? Is this information part of the command, part of the backend state, or part of the frontend state? How to restore this state in the frontend when the user has a network problem and refreshes the browser page completely (ctrl-R or shift-ctrl-R)?
These considerations are solved easily for a pure SPA, because there is only one Application state - the frontend one. (The SPA backend APIs are, in a sense, just a persistence layer). That is not the case with any of the Laravel UI solutions -- at least as much as I know. It would be great to have some help and best practices on how to tackle undo/redo with Laravel and its UI solutions. The problem will become more and more important as rich web applications replace old-style ones and as autosaving becomes the norm.
Thanks!