From 3d43964bcdfe515031446c8d2620f4c70871a6c8 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 27 May 2021 13:20:37 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20portal=20preview=20resiz?= =?UTF-8?q?e=20when=20using=20split=20front-end/admin=20URLs=20(#1980)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - switched to listening to Portal's `message` events that now include a height - removes need to reach into Portal preview iframe contents which is blocked by browser security when working cross-origin --- ghost/admin/app/components/gh-site-iframe.hbs | 1 + ghost/admin/app/components/gh-site-iframe.js | 6 +- .../app/controllers/settings/membership.js | 58 +++++++------------ .../app/templates/settings/membership.hbs | 2 +- 4 files changed, 28 insertions(+), 39 deletions(-) diff --git a/ghost/admin/app/components/gh-site-iframe.hbs b/ghost/admin/app/components/gh-site-iframe.hbs index ecb5915eac..29cbbd55cd 100644 --- a/ghost/admin/app/components/gh-site-iframe.hbs +++ b/ghost/admin/app/components/gh-site-iframe.hbs @@ -3,6 +3,7 @@ src={{this.srcUrl}} frameborder="0" allowtransparency="true" + {{did-insert (optional @onInserted)}} {{did-insert this.attachMessageListener}} {{did-update this.resetSrcAttribute @guid}} {{on "load" this.onLoad}} diff --git a/ghost/admin/app/components/gh-site-iframe.js b/ghost/admin/app/components/gh-site-iframe.js index b689eb2cd1..32f9e7c65f 100644 --- a/ghost/admin/app/components/gh-site-iframe.js +++ b/ghost/admin/app/components/gh-site-iframe.js @@ -62,11 +62,15 @@ export default class GhSiteIframeComponent extends Component { attachMessageListener() { if (typeof this.args.invisibleUntilLoaded === 'string') { this.messageListener = (event) => { + if (this.isDestroying || this.isDestroyed) { + return; + } + const srcURL = new URL(this.srcUrl); const originURL = new URL(event.origin); if (originURL.origin === srcURL.origin) { - if (event.data === this.args.invisibleUntilLoaded) { + if (event.data === this.args.invisibleUntilLoaded || event.data.type === this.args.invisibleUntilLoaded) { this.makeVisible.perform(); } } diff --git a/ghost/admin/app/controllers/settings/membership.js b/ghost/admin/app/controllers/settings/membership.js index 9f82849d1b..ad9d2536ee 100644 --- a/ghost/admin/app/controllers/settings/membership.js +++ b/ghost/admin/app/controllers/settings/membership.js @@ -4,7 +4,6 @@ import {action} from '@ember/object'; import {currencies, getCurrencyOptions, getSymbol} from 'ghost-admin/utils/currency'; import {inject as service} from '@ember/service'; import {task} from 'ember-concurrency-decorators'; -import {timeout} from 'ember-concurrency'; import {tracked} from '@glimmer/tracking'; const CURRENCIES = currencies.map((currency) => { @@ -241,20 +240,36 @@ export default class MembersAccessController extends Controller { newUrl.searchParams.set('v', this.portalPreviewGuid); this.portalPreviewUrl = newUrl; - - this.resizePortalPreviewTask.perform(); } @action - portalPreviewLoaded(iframe) { + portalPreviewInserted(iframe) { this.portalPreviewIframe = iframe; - this.resizePortalPreviewTask.perform(); + + if (!this.portalMessageListener) { + this.portalMessageListener = (event) => { + // don't resize membership portal preview when events fire in customize portal modal + if (this.showPortalSettings) { + return; + } + + const resizeEvents = ['portal-ready', 'portal-preview-updated']; + if (resizeEvents.includes(event.data.type) && event.data.payload?.height) { + this.portalPreviewIframe.parentNode.style.height = `${event.data.payload.height}px`; + } + }; + + window.addEventListener('message', this.portalMessageListener, true); + } } @action portalPreviewDestroyed() { this.portalPreviewIframe = null; - this.resizePortalPreviewTask.cancelAll(); + + if (this.portalMessageListener) { + window.removeEventListener('message', this.portalMessageListener); + } } @task @@ -262,37 +277,6 @@ export default class MembersAccessController extends Controller { return yield this.saveSettingsTask.perform({forceRefresh: true}); } - @task({restartable: true}) - *resizePortalPreviewTask() { - if (this.portalPreviewIframe && this.portalPreviewIframe.contentWindow) { - yield timeout(100); // give time for portal to re-render - - try { - const portalIframe = this.portalPreviewIframe.contentWindow.document.querySelector('#ghost-portal-root iframe'); - if (!portalIframe) { - return; - } - - portalIframe.contentWindow.document.body.style.overflow = 'hidden'; - portalIframe.contentWindow.document.body.style['scrollbar-width'] = 'none'; - - const portalContainer = portalIframe.contentWindow.document.querySelector('.gh-portal-popup-container'); - if (!portalContainer) { - return; - } - - const height = portalContainer.clientHeight; - this.portalPreviewIframe.parentNode.style.height = `${height}px`; - } catch (e) { - if (e.name === 'SecurityError') { - // cross-origin blocked - return; - } - throw e; - } - } - } - async saveProduct() { const isStripeConnected = this.settings.get('stripeConnectAccountId'); if (this.product && isStripeConnected) { diff --git a/ghost/admin/app/templates/settings/membership.hbs b/ghost/admin/app/templates/settings/membership.hbs index b8fdbcbe6f..ed052ff1e8 100644 --- a/ghost/admin/app/templates/settings/membership.hbs +++ b/ghost/admin/app/templates/settings/membership.hbs @@ -59,7 +59,7 @@ scrolling="no" @src={{this.portalPreviewUrl}} @invisibleUntilLoaded="portal-ready" - @onLoad={{this.portalPreviewLoaded}} + @onInserted={{this.portalPreviewInserted}} @onDestroyed={{this.portalPreviewDestroyed}} /> {{/if}}