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}}