0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Added throttling and animation when updating signup form preview

fixes https://github.com/TryGhost/Team/issues/3378
This commit is contained in:
Simon Backx 2023-06-05 15:24:59 +02:00
parent c2c6e54578
commit 22f4d55f75
4 changed files with 91 additions and 56 deletions

View file

@ -24,16 +24,18 @@
/>
</div>
<div class="gh-stack-item row">
<label class="modal-fullsettings-title">
Background color
</label>
<Modals::Newsletters::Components::ColorPicker
@color={{this.backgroundColor}}
@presetColors={{this.backgroundPresetColors}}
@onColorChange={{this.setBackgroundColor}}
/>
</div>
{{#unless (eq this.style 'minimal')}}
<div class="gh-stack-item row">
<label class="modal-fullsettings-title">
Background color
</label>
<Modals::Newsletters::Components::ColorPicker
@color={{this.backgroundColor}}
@presetColors={{this.backgroundPresetColors}}
@onColorChange={{this.setBackgroundColor}}
/>
</div>
{{/unless}}
<div class="gh-stack-item">
<label class="modal-fullsettings-title">

View file

@ -1,11 +1,19 @@
<div>
<div {{did-update this.onChangeHtml @html}}>
<iframe
srcDoc="<!DOCTYPE html>"
class="gh-signup-form-iframe"
class={{if (eq this.visibleIframeIndex 0) "gh-signup-form-iframe" "gh-signup-form-iframe gh-iframe-hidden"}}
frameborder="0"
allowtransparency="true"
title="Signup Form Preview"
{{on "load" this.onLoad}}
{{did-update this.updateContent @html}}
title="Signup Form Preview 1"
{{on "load" (fn this.onLoad 0) }}
></iframe>
<iframe
srcDoc="<!DOCTYPE html>"
class={{if (eq this.visibleIframeIndex 1) "gh-signup-form-iframe" "gh-signup-form-iframe gh-iframe-hidden"}}
frameborder="0"
allowtransparency="true"
title="Signup Form Preview 2"
{{on "load" (fn this.onLoad 1)}}
></iframe>
</div>

View file

@ -1,59 +1,74 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {throttle} from '@ember/runloop';
import {tracked} from '@glimmer/tracking';
export default class Preview extends Component {
iframe;
iframeRoot;
isContentLoaded = false;
// We have two iframes
// When the HTML changes, the invisible iframe will get changed, once that one is fully loaded, it will become visible and the other iframe will be hidden
/**
* When updating the frame, to avoid layout jumps, we'll reuse the last known height
*/
@tracked
cachedHeight = 0;
iframes = [
{element: null, html: '', loading: true},
{element: null, html: '', loading: true}
];
@action
onLoad(event) {
this.iframe = event.currentTarget;
if (!this.isContentLoaded) {
this.updateContent();
}
this.onResize();
(new ResizeObserver(() => this.onResize(this.iframeRoot)))?.observe?.(this.iframeRoot);
@tracked
visibleIframeIndex = 0;
get visibleHtml() {
return this.iframes[this.visibleIframeIndex].html;
}
@action
updateContent() {
if (!this.iframe) {
onLoad(index, event) {
const iframe = this.iframes[index];
if (!iframe) {
return;
}
if (!iframe.element) {
iframe.element = event.currentTarget;
if (index === this.visibleIframeIndex) {
this.updateContent(index);
}
} else {
// Finished loading this iframe
iframe.loading = false;
this.visibleIframeIndex = index;
}
}
@action onChangeHtml() {
// Get next iframe
throttle(this, this.throttledUpdate, 300, false);
}
throttledUpdate() {
// Update the invisible iframe content
const index = this.visibleIframeIndex === 0 ? 1 : 0;
this.updateContent(index);
}
@action
updateContent(index) {
const iframe = this.iframes[index];
if (!iframe || !iframe.element) {
return;
}
if (index === this.visibleIframeIndex && !iframe.loading) {
return;
}
iframe.loading = true;
const html = `<html><head><style>body, html {padding: 0; margin: 0;}</style></head><body>${this.args.html}</body></html>`;
iframe.html = this.args.html;
// Set the iframe's new HTML
this.iframe.contentWindow.document.open();
this.iframe.contentWindow.document.write(html);
this.iframe.contentWindow.document.close();
this.iframeRoot = this.iframe.contentDocument.body;
// fix for Safari causing the iframe load to inifite loop
// Set the flag indicating the content has been loaded
this.isContentLoaded = true;
}
@action
onResize() {
if (!this.iframeRoot) {
return;
}
const height = this.iframeRoot.scrollHeight || this.cachedHeight;
//this.iframe.style.height = `${height}px`;
if (height > 30) {
this.cachedHeight = height;
}
iframe.element.contentWindow.document.open();
iframe.element.contentWindow.document.write(html);
iframe.element.contentWindow.document.close();
}
}

View file

@ -3081,6 +3081,16 @@ p.theme-validation-details {
.gh-signup-form-iframe {
width: 100%;
border: 0;
opacity: 1;
z-index: 0;
transition: none;
}
.gh-signup-form-iframe.gh-iframe-hidden {
opacity: 0;
z-index: 1;
transition: 0.3s opacity;
pointer-events: none;
}
.fullwidth-modal {