-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
After #7 gets a first pass, I want to start thinking about system-wide undo/history patterns. I feel a little silly saying, "now that some rickety basics are in place, let's implement time travel" but it's something that I want to bake into the design as a possibility. It's such a huge rabbit hole but informs some choices now like the serializable action system, so I want to keep it in mind without going down the rabbit holes. This is getting me to think about UI snapshotting/restoring and incremental mutations, something to work through regardless of time travel -- they're related and enabled by some shared primitives.
The goal for this issue is to figure out an initial strategy. I don't expect global undo from it, I'm skeptical it's even possible or advisable to try without adding bad constraints or regrettable problems.
Some examples I think about include image editors and spreadsheets. One UX I think about is the user saying "wait I didn't mean to do that" but without undo toasts urgently popping. For implementation, revertability by creating new actions seems to make sense for the cases where literal snapshot rollback isn't appropriate. Maybe "system-wide undo/history patterns" isn't the right way to think about it, and instead maybe there's no one system, but basic affordances of the system could support these patterns for specific needs.
One way would be to use something like JSON Patch via Immer, but I want to make sure it leverages Svelte runes to the max, given $snapshot and the current Cell design using $state/$derived in a tree. I'm wary of making dependency choices this fundamental without very clear guidance from use cases. The performance characteristics are also important to get right, some simple designs look unworkably slow/wasteful. I'm thinking about granularity, incremental computation, and the differences between diff-stream patches and serialized action history. Full-on event sourcing is too much of a "big idea" design for me to attempt because of the problems it creates, but letting users explore by opting into storing action history, with a plugin or config option? Maybe that's the best design direction for now.
There's some localized behavior with diskfile history that can be referenced, and that code should probably be integrated with new generic systems. It should be designed with the Cell and snapshotting/restoring in mind, but idk what its structure should look like or how decoupled it should be. I wonder if participation in this system could be a property of the action specs (partially? maybe with granular overrides).
This gets me thinking about Git and CRDTs. Maybe deeper Git integration is a better use of time. There's a lot of interesting work happening with CRDTs, and my sense right now is that they will be useful in specific contexts, but our preferred base behavior will use the backend's database (Postgres or pglite) with less fancy syncing. It's a very big topic, maybe too distracting, but opens up seemingly important use cases, so I want to plan with it in mind.