User tests: Successful: Unsuccessful:
Pull Request for Issue # .
Added Undo/Redo functionality for MediaManager Plugins.
All changes will be saved in a history, and can then be undone or redone with the buttons in the menu.
This could also be used to preserve the state of the plugin. As of now, if a change has been made and then the plugin is switched, the changes will be applied in a destructive way, and returning back to the plugin does not allow to return to the original state (For example: crop an image, switch to resize, go back to cropping and you will find, that it is not possible to extend the cropped area back to the images original size). The history stores the plugin state as well, and this could be used in a later PR to restore the state of the plugin.
Edit an image in the MediaManager and click undo or redo in the menu to revert or redo the changes.
Status | New | ⇒ | Pending |
Category | ⇒ | Administration com_media Language & Strings JavaScript Repository NPM Change |
Didn't do a code review, @dgrammatiko any feedback?
The code seems fine. Although when I added the @todos
in the script I had a different implementation on my mind:
EDIT The current implementation actually stores the plugin state so that's ok (the second point)
Labels |
Added:
?
NPM Resource Changed
?
|
Category | Administration com_media Language & Strings JavaScript Repository NPM Change | ⇒ | Administration com_media Language & Strings JavaScript Repository NPM Change SQL Installation Postgresql |
I have added a length limit option.
@dgrammatiko As for the first point, I believe I have already solved this by changing the events on which the history points are stored. They are only sent once a change has been made and not multiple times during the change how it was implemented before. For the last point I have added an option in the settings to limit the history length.
To restore the plugins state, I'm still trying to figure out a solution. I do store the plugins state, but since the changed image is rendered and stored every time the plugin changes, I would need to somehow go over each plugin and apply the changes to the original image again. So for example, if my first change is cropping the image, and then I switch to resize and change the size, I'm applying this to the already cropped image. If I go back to the crop plugin, I would need to apply the crop to the original image to allow the user to extend the crop area, but then I would also need to apply resize (and all other changes made in other plugins) to the original image as well. Any thougths?
@vlaucht I think there is a fundamental piece missing here, you need to register the plugin execution function with their payload in order to replay them. A thought experiment, that will probably work in this context is like:
// Create an API point that all plugins run in order to execute a command
// Execute Plugin Command
Joomla.MediaManager.execCommand = (command, payload) => {
new Promise(command({ ...payload }))
.then(resolve => storeToHistory)
.catch(rollbackLastHistoryEntry);
};
// The history store also needs to change a little bit like
// I think what you have right now is an array of {file: 'string', data: 'string'}
which should become
{
file: 'string',
data: 'string',
command: 'string',
payload: {}
}
// Maybe also you need to store the plugin name and the tab index
// So you could safely switch to the right context (execCommand will need to switch plugins iirc)
The combination of these changes should allow you to replay safely any plugin command. Of course, quite some checks need to be implemented but I think this approach is viable
Right now it stores the following:
{
file: 'string',
data: {
pluginName (e.g. 'crop'): { pluginData (e.g. width, heigth },
}
}
So do you mean I need to implement an exec function and then run it for each plugin in order to restore the images state?
So do you mean I need to implement an exec function and then run it for each plugin in order to restore the images state?
I think it's safe to assume that there might be some intermediate functions in the chain of execution. Eg an input has an oninput
event that executes a function and manipulates the value before handing it to the execution function, so by storing only the form data is not safe for replaying the command. I think the idea to have an API that is called per plugin command is the only safe way here. By the way the implementation of the history will also be simpler (the history points will derive from the executed commands, sequentially, so theoretically it should need less pampering)
Ah, I see.
But this still only works per plugin. It doesnt solve the issue how to restore all other plugins simultaneously.
So if I apply crop to an image (see step2) and then rotate it (step3) and then go back to crop and want to increase the cropped area, I cant (step4), because it is already rendered. So I need to apply the crop effect stored in the history again to the original image, to let me increase the cropped area. But then I would also need to apply rotate to this image again. Same goes for all other plugins applied in between.
But this still only works per plugin. It doesnt solve the issue how to restore all other plugins simultaneously.
That's the reason for a promise based solution. I had a comment Maybe also you need to store the plugin name and the tab index
which means that if you want to undo 2 steps the program will queue 2 commands (history -1 and then history - 2) and execute them sequentially. Also the tab select iirc correctly has already some initialization code for each plugin, thus you also have to replay that part (afaik right now this is synchronous so it might have to be done in an async way (promise or await) to make sure you don't end up in race conditions
and then go back to crop and want to increase the cropped area, I cant (step4)
Not all commands will be always executable and that is expected (also in photoshop you don't get to redo everything), thus the catch part, you can throw am alert, something like this command cannot be re-applied, due to changed dimensions
or something along that line
When you make a change without the patch applied, clicking the reset button returns you back to the first history point (original loading of the image you're editing).
When you make a change with the patch applied, clicking the reset button does nothing now.
Aside from that, very nice addition to the Media Manager.
I have tested this item
Addition of Undo/Redo breaks Reset functionality per the above (Seems I missed hitting submit on this last night when testing.)
Addition of Undo/Redo breaks Reset functionality per the above
Save is a destructing actions or plain English: reset only works from the last loaded image (when you hit save the saved image is your new starting point). That was the initial implementation AFAIR so there is nothing broken here
I have tested this item
Title |
|
Please can you fix the merge issues with the Conflicting files so that this can be retested.
This pull request has automatically rebased to 4.2-dev.
Good idea, thanks for proposing the feature.
Closing this PR because of inactivity for a longer time.
Status | Pending | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2022-10-21 10:14:14 |
Closed_By | ⇒ | rdeutz | |
Labels |
Added:
Language Change
Ready to take over
Conflicting Files
?
Removed: ? ? |
#PROD2020/024 - There shall be no indiscriminate closing of Issues or Pull Requests
Closing of Issues and Pull requests PR's shall NOT be done without underlying rationale and individual reasoning in the Issue or PR. Elapsing of a time period, inactivity of the submitter are examples that do NOT constitute valid reasons in and by themselves.
I have tested this item✅ successfully on 4b2b742
Good work!!
This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30511.