From a817a865c37b3ce39a143efd97fd8a9aa74bf3d8 Mon Sep 17 00:00:00 2001 From: abd-msyukyu-odoo Date: Thu, 1 Dec 2022 09:24:49 +0000 Subject: [PATCH] [FIX] web_editor,knowledge: suspend wysiwyg onBlur with dialogs Sometimes, there is a crash when uploading a file when loading an article for the first time. Impacted versions: 16.0+ How to reproduce: - open the odoo home page (module menu) and CTRL+f5 (force reload) - go to the knowledge app - in an article, put the cursor somewhere and type ENTER to create a new line - type the /file command in that line - try to upload a file - traceback (if it does not happen, try again from the first step, it is not always consistent) Fix: Delay the _onBlur handling of the wysiwig when using the modal. The Blur event may occur and may trigger an update on the html_field, which may in turn induce a rerendering of the component and its value. We don't want this to occur when using the modal, because the selection was registered by the modal to restore it when the modal closes (`preserveCursor`). If the contents of the html_field are updated, then the stored position used to restore the selection won't be in the DOM anymore, and the restoration will fail. As such when we try to insert the Knowledge file block, the selection is not in the editor and the method fails. Task-2889670 Task-3128388 Task-3086694 X-original-commit: 2591d343793f59e2e70e7ffe8fa666661995348f Part-of: odoo/odoo#110089 Co-authored-by: Antoine Guenet --- addons/web_editor/static/src/js/wysiwyg/wysiwyg.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index 5bb6c8b4b7e..bfdea46b331 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -1356,6 +1356,11 @@ const Wysiwyg = Widget.extend({ const field = $editable.data('oe-field'); const type = $editable.data('oe-type'); + // The html_field value should not be updated while the mediaDialog is + // in use because if its value change, restoreSelection may fail since + // it has a reference to HTMLElements which are not in the DOM anymore. + this._shouldDelayBlur = true; + this.mediaDialogWrapper = new ComponentWrapper(this, MediaDialogWrapper, { resModel: model, resId: $editable.data('oe-id'), @@ -2445,8 +2450,9 @@ const Wysiwyg = Widget.extend({ if (!e.target.classList.contains('o_editable_date_field_linked')) { this.$editable.find('.o_editable_date_field_linked').removeClass('o_editable_date_field_linked'); } - if (e.target.closest('.oe-toolbar')) { - this._onToolbar = true; + const closestDialog = e.target.closest('.o_dialog, .o_web_editor_dialog'); + if (e.target.closest('.oe-toolbar') || (closestDialog && closestDialog.querySelector('.o_select_media_dialog, .o_link_dialog'))) { + this._shouldDelayBlur = true; } else { if (this._pendingBlur && !e.target.closest('.o_wysiwyg_wrapper')) { // todo: to remove when removing the legacy field_html @@ -2454,11 +2460,11 @@ const Wysiwyg = Widget.extend({ this.options.onWysiwygBlur && this.options.onWysiwygBlur(); this._pendingBlur = false; } - this._onToolbar = false; + this._shouldDelayBlur = false; } }, _onBlur: function () { - if (this._onToolbar) { + if (this._shouldDelayBlur) { this._pendingBlur = true; } else { // todo: to remove when removing the legacy field_html