[IMP] web_editor: perf; skip mutually-cancelling actions in editor
Previously, when the user quickly hovered over many options (eg when trying to click on the last item of a select menu), all of the options that were briefly hovered would be previewed in succession. While this is not a problem for options that are fast to change, some option take some time (eg, image filters), but all of the intermediary previews would still show one after another, which is both very slow and completely useless. This commit adds a per-widget action queue. When a widget is called, it will immediately add an action item to this queue, but when the snippet_edition mutex becomes available to execute this action, it will first check that this action will not be immediately reverted, and if it will, the action is skipped entirely. task-2337344 closes odoo/odoo#58256 X-original-commit: 4d1e47213627304329fa438cae6d6c58484dbb32 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -1816,6 +1816,7 @@ const SnippetOptionWidget = Widget.extend({
|
||||
this.ownerDocument = this.$target[0].ownerDocument;
|
||||
|
||||
this._userValueWidgets = [];
|
||||
this._actionQueues = new Map();
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
@@ -2684,9 +2685,34 @@ const SnippetOptionWidget = Widget.extend({
|
||||
}
|
||||
}
|
||||
|
||||
// Queue action so that we can later skip useless actions.
|
||||
if (!this._actionQueues.get(widget)) {
|
||||
this._actionQueues.set(widget, []);
|
||||
}
|
||||
const currentAction = {previewMode};
|
||||
this._actionQueues.get(widget).push(currentAction);
|
||||
|
||||
// Ask a mutexed snippet update according to the widget value change
|
||||
const shouldRecordUndo = (!previewMode && !ev.data.isSimulatedEvent);
|
||||
this.trigger_up('snippet_edition_request', {exec: async () => {
|
||||
// Filter actions that are counterbalanced by earlier/later actions
|
||||
const actionQueue = this._actionQueues.get(widget).filter(({previewMode}, i, actions) => {
|
||||
const prev = actions[i - 1];
|
||||
const next = actions[i + 1];
|
||||
if (previewMode === true && next && next.previewMode) {
|
||||
return false;
|
||||
} else if (previewMode === 'reset' && prev && prev.previewMode) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// Skip action if it's been counterbalanced
|
||||
if (!actionQueue.includes(currentAction)) {
|
||||
this._actionQueues.set(widget, actionQueue);
|
||||
return;
|
||||
}
|
||||
this._actionQueues.set(widget, actionQueue.filter(action => action !== currentAction));
|
||||
|
||||
if (ev.data.prepare) {
|
||||
ev.data.prepare();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user