From fe388460d86427d35d44c4d8a431ca97f754bb0f Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Thu, 17 Sep 2020 12:14:48 +0000 Subject: [PATCH] [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) --- .../static/src/js/editor/snippets.options.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index 9b1ca9feadd..54cef702bc2 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -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(); }