0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Added performance adjustments to Portal iFrames (#19373)

refs PROD-4
This commit is contained in:
Ronald Langeveld 2023-12-14 06:54:39 +02:00 committed by GitHub
parent dc7e2b9261
commit 275cdd4db9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,37 +1,51 @@
import React, {useEffect, useRef, useState} from 'react'; import React, {useCallback, useEffect, useRef, useState} from 'react';
type PortalFrameProps = { type PortalFrameProps = {
selectedTab?: string;
href: string; href: string;
onLoaded?: (iframe: HTMLIFrameElement) => void;
onDestroyed?: () => void;
selectedTab?: string;
} }
// we should refactor this to be reused in offers as well const PortalFrame: React.FC<PortalFrameProps> = ({href, onLoaded, onDestroyed, selectedTab}) => {
const PortalFrame: React.FC<PortalFrameProps> = ({selectedTab, href}) => {
if (!selectedTab) { if (!selectedTab) {
selectedTab = 'signup'; selectedTab = 'signup';
} }
const iframeRef = useRef<HTMLIFrameElement>(null); const iframeRef = useRef<HTMLIFrameElement>(null);
const [portalReady, setPortalReady] = useState(false); const [isInvisible, setIsInvisible] = useState<boolean>(true);
// Handler for making the iframe visible, memoized with useCallback
const makeVisible = useCallback(() => {
setTimeout(() => {
setIsInvisible(false);
if (onLoaded && iframeRef.current) {
onLoaded(iframeRef.current);
}
}, 100); // Delay to allow scripts to render
}, [onLoaded]); // Dependencies for useCallback
// Effect for attaching message listener
useEffect(() => { useEffect(() => {
const messageListener = (event: MessageEvent<'portal-ready' | {type: string}>) => { const messageListener = (event: MessageEvent) => {
if (!href) { if (!href) {
return; return;
} }
const srcURL = new URL(href);
const originURL = new URL(event.origin); const originURL = new URL(event.origin);
if (originURL.origin === srcURL.origin) { if (originURL.origin === new URL(href).origin) {
if (event.data === 'portal-ready' || event.data.type === 'portal-ready') { if (event.data === 'portal-ready' || event.data.type === 'portal-ready') {
setPortalReady(true); makeVisible();
} }
} }
}; };
window.addEventListener('message', messageListener, true); window.addEventListener('message', messageListener, true);
return () => window.removeEventListener('message', messageListener, true);
}, [href]); return () => {
window.removeEventListener('message', messageListener, true);
onDestroyed?.();
};
}, [href, onDestroyed, makeVisible]);
if (!href) { if (!href) {
return null; return null;
@ -41,13 +55,14 @@ const PortalFrame: React.FC<PortalFrameProps> = ({selectedTab, href}) => {
<> <>
<iframe <iframe
ref={iframeRef} ref={iframeRef}
className={!portalReady ? 'hidden' : ''} className={!isInvisible ? '' : 'hidden'}
data-testid="portal-preview" data-testid="portal-preview"
height="100%" height="100%"
src={href} src={href}
title="Portal Preview" title="Portal Preview"
width="100%" width="100%"
></iframe> onLoad={makeVisible}
/>
</> </>
); );
}; };