Plugin state after undo/redo

I was wondering what is the suggested way to maintain some context about the changes as undo/redo occurs. I’ve read this post about plugin state in undo history and this one about someone considering using a step to store the plugin state but seems like that was frowned upon as its not really a document change. But I’m hoping maybe something has changed since.

Essentially I have a plugin (similar to suggest/mention) that when one types the trigger character (e.g. @) a popup is displayed but that shouldn’t be displayed for other end user actions (e.g. pasting) so the state is determined/set from methods like handleTextInput. While it is open the state is updated/maintained as changes occur - e.g. typing, deleting characters, changing selection, etc. If an undo happens while it’s open then it’s ok because the apply of the plugin’s state is given the old state and a new state can be calculated. So for example you type ‘@joe’ and then undo and perhaps it removes the ‘oe’ then the state is updated accordingly.

The problem I have is when the popup is closed - e.g. when one presses escape or chooses an item from the list. At that point the state of the plugin is removed from the editor state. If you undo at that point the apply is given the old state but that’s null so no new state can be calculated and there’s nothing else I can see that would give me some hint about the context of those changes. The preferred result is if those changes being undone were the result of typing that I might reshow the popup. I was hoping perhaps the undo would persist the plugin state (or that there be some way to indicate that particular plugin state should be persisted) but it seems like it’s only keeping step related info. What is the recommended approach here? Is there some other mechanism I missed that would deal with this already or would I need to extend the history to store add’l state? I’m sure it’s more involved than that if collaboration were involved (it’s not in my case) since that context would/could be specific to the user that performed the action initially.

There’s no existing mechanism that will handle this for you. Do I understand correctly that you want closing the dialog to be undoable? Custom steps might work in your use case, but I haven’t actually used them in such a context, so you’d have to see.

It’s a popup much like the one in this site so not so much a dialog but yeah the gist would be that i would want the popup to reopen if the undo backs up to a point where the plugin state was there. I haven’t had a chance to try out the custom step as this is low priority but will try that out when I do get a chance. Thanks

We had a similar need and we ended up using a custom meta step. The trick is to define the previous metadata in addition to the new metadata you want to set when creating your step. That way, you can correctly implement the “invert” function in your custom step by just swapping the previous metadata and current metadata.

Then in your plugin that references the metadata, you just do tr.steps.find in your state->apply function to find your custom step and use metadata attached to the step to set your plugin state.