Skip to content
Snippets Groups Projects
Commit b65623c8 authored by Marius Dumitru Florea's avatar Marius Dumitru Florea
Browse files

XWIKI-22551: Information box content lost when multiple users update the macro...

XWIKI-22551: Information box content lost when multiple users update the macro parameters at the same time
* Wait for the editor to be ready before focusing it when coming back from the macro wizard.
* Mark the editor ready after the event loop (i.e. with a slight delay) and double check that it's ready
* Update widget selection after restoring the selection as a result of a remote change
parent eebf3d83
No related branches found
No related tags found
No related merge requests found
...@@ -93,14 +93,26 @@ ...@@ -93,14 +93,26 @@
editor.toBeReady = function() { editor.toBeReady = function() {
return new Promise(resolve => { return new Promise(resolve => {
function resolveWhenReady() {
// Announce that the editor is ready only after the event loop has finished, to allow the code that
// triggered the event to finish its execution. This is important for instance in the case of the refresh
// command which needs to end the editor loading state before it can restore the selection (the editing area
// needs to be visible and have the focus).
setTimeout(async () => {
// Double check that the editor is ready, because other event listeners or some remote change might have
// updated the editor status in the meantime.
await editor.toBeReady();
resolve();
}, 0);
}
if (loadingCounter > 0) { if (loadingCounter > 0) {
this.once('endLoading', resolve); this.once('endLoading', resolveWhenReady);
} else if (this.status === 'ready') { } else if (this.status === 'ready') {
resolve(); resolve();
} else if (this.status === 'recreating') { } else if (this.status === 'recreating') {
this.once('contentDom', resolve); this.once('contentDom', resolveWhenReady);
} else { } else {
this.on('instanceReady', resolve); this.on('instanceReady', resolveWhenReady);
} }
}); });
}; };
......
...@@ -307,19 +307,37 @@ ...@@ -307,19 +307,37 @@
}, options.commandData)); }, options.commandData));
}, },
showMacroWizard: function(macroCall) { showMacroWizard: function(macroCall) {
var widget = this; // We don't use _showMacroWizard directly as RequireJS callback because it is asynchronous and RequireJS has
var input = { // issues with async callbacks. See https://github.com/requirejs/requirejs/issues/1694 .
require(['macroWizard'], (macroWizard) => {
this._showMacroWizard(macroWizard, macroCall);
});
},
_showMacroWizard: async function(macroWizard, macroCall) {
// Show the macro wizard to insert or edit a macro and wait for the result.
const widget = this;
const input = {
macroCall: macroCall, macroCall: macroCall,
hiddenMacroParameters: Object.keys(widget.editables || {}), hiddenMacroParameters: Object.keys(widget.editables || {}),
sourceDocumentReference: editor.config.sourceDocument.documentReference sourceDocumentReference: editor.config.sourceDocument.documentReference
}; };
// Show our custom insert/edit dialog. let output;
require(['macroWizard'], function(macroWizard) { try {
// Give the focus back to the editor after the modal is closed. output = await macroWizard(input);
macroWizard(input).always(editor.focus.bind(editor)).done(function(data) { } catch (e) {
macroPlugin.insertOrUpdateMacroWidget(editor, data, widget); // The macro wizard was canceled.
}); }
});
// Give the focus back to the editor after the modal is closed. We need to wait for the editor to be ready
// because remote changes might have put the editor in loading mode while the macro wizard was open (e.g. if
// another user inserted a macro which triggered a content refresh).
await editor.toBeReady();
editor.focus();
// Update or insert the macro widget based on the output of the macro wizard.
if (output) {
macroPlugin.insertOrUpdateMacroWidget(editor, output, widget);
}
} }
}); });
......
...@@ -142,6 +142,10 @@ define('xwiki-ckeditor-realtime-adapter', [ ...@@ -142,6 +142,10 @@ define('xwiki-ckeditor-realtime-adapter', [
/** @inheritdoc */ /** @inheritdoc */
restoreSelection(ranges) { restoreSelection(ranges) {
this._CKEDITOR.plugins.xwikiSelection.restoreSelection(this._ckeditor, ranges); this._CKEDITOR.plugins.xwikiSelection.restoreSelection(this._ckeditor, ranges);
// Update the focused and selected widgets, as well as the widget holding the focused editable, after the
// selection is restored.
this._ckeditor.widgets.checkSelection();
} }
/** @inheritdoc */ /** @inheritdoc */
...@@ -390,10 +394,6 @@ define('xwiki-ckeditor-realtime-adapter', [ ...@@ -390,10 +394,6 @@ define('xwiki-ckeditor-realtime-adapter', [
if (shouldRefreshContent) { if (shouldRefreshContent) {
await this._refreshContent(); await this._refreshContent();
} }
// Update the focused and selected widgets, as well as the widget holding the focused editable, after the
// selection is restored.
setTimeout(() => this._ckeditor.widgets.checkSelection(), 0);
} }
async _refreshContent() { async _refreshContent() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment