[FIX] website: unblock iframe on not editable content

Before this commit, following those steps:
- Go to /hello.css
- Create the page/file
- View in page manager
- Click on its row
-> You're redirected to the file, with infinite loading

This commit fixes this behaviour by unblocking the iframe:
- on the OdooFrameContentLoaded event for frontend pages
- on the load event for other pages

To do that, the BlockIframe component is changed to handle process ids.
Before this commit, the BlockIframe component would count the calls to
block or unblock the iframe (and store it in an iframeLocks variable),
so that multiple processes can block the iframe independently from each
other.
As an exemple, for two processes A and B, the iframe should remain
blocked during those two processes, and released at the end:
(A) blockIframe => (B) blockIframe => (B) unblockIframe => (A)
unblockIframe.

But that iframeLocks variable was fragile: a process that blocks the
iframe should unblock it once, otherwise it would mess up the locks
count. It was not appropriate for a process that could be ended with two
events, for example loading the iframe. The first of the 'load' or
'OdooFrameContentLoaded' events should unblock it.

To change that, a process can block the iframe with a processId. The
first unblock call with the same processId will unblock the iframe, the
other ones will be ignored.

task-2687506

Part-of: odoo/odoo#95955
This commit is contained in:
Younn Olivier
2022-07-18 18:41:28 +02:00
parent 2e6b59a8e4
commit 72051ad58a
2 changed files with 20 additions and 14 deletions
@@ -18,7 +18,8 @@ class BlockIframe extends Component {
blockIframe: false,
showLoader: false,
});
this.iframeLocks = 0;
this.processes = [];
this.ANONYMOUS_PROCESS_ID = 'ANONYMOUS_PROCESS_ID';
this.websiteService.bus.addEventListener("BLOCK", this.block.bind(this));
this.websiteService.bus.addEventListener("UNBLOCK", this.unblock.bind(this));
}
@@ -28,17 +29,18 @@ class BlockIframe extends Component {
this.state.showLoader = true;
}, event.detail.loaderDelay);
}
if (this.iframeLocks === 0) {
if (!this.processes.length) {
this.state.blockIframe = true;
}
this.iframeLocks++;
this.processes.push(event.detail.processId || this.ANONYMOUS_PROCESS_ID);
}
unblock() {
this.iframeLocks--;
if (this.iframeLocks < 0) {
this.iframeLocks = 0;
unblock(event) {
const processId = event.detail.processId || this.ANONYMOUS_PROCESS_ID;
const processIndex = this.processes.indexOf(processId);
if (processIndex > -1) {
this.processes.splice(processIndex, 1);
}
if (this.iframeLocks === 0) {
if (this.processes.length === 0) {
this.state.blockIframe = false;
this.state.showLoader = false;
}
@@ -95,8 +97,12 @@ export class WebsitePreview extends Component {
}, () => [this.props.action.context.params]);
useEffect(() => {
this.websiteService.blockIframe();
this.iframe.el.addEventListener('OdooFrameContentLoaded', () => this.websiteService.unblockIframe(), { once: true });
this.websiteService.blockIframe(true, 0, 'load-iframe');
this.iframe.el.addEventListener('load', () => this.websiteService.unblockIframe('load-iframe'), { once: true });
// For a frontend page, it is better to use the
// OdooFrameContentLoaded event to unblock the iframe, as it is
// triggered faster than the load event.
this.iframe.el.addEventListener('OdooFrameContentLoaded', () => this.websiteService.unblockIframe('load-iframe'), { once: true });
}, () => []);
}
@@ -192,11 +192,11 @@ export const websiteService = {
}
return Wysiwyg;
},
blockIframe(showLoader = true, loaderDelay = 0) {
bus.trigger('BLOCK', {showLoader, loaderDelay});
blockIframe(showLoader = true, loaderDelay = 0, processId) {
bus.trigger('BLOCK', {showLoader, loaderDelay, processId});
},
unblockIframe() {
bus.trigger('UNBLOCK');
unblockIframe(processId) {
bus.trigger('UNBLOCK', { processId });
},
leaveEditMode() {
// FIXME this does not care about if the page is dirty or not.