shell bypass 403
import {
useState,
useLayoutEffect,
useRef,
useCallback,
} from '@wordpress/element';
import { debounce } from 'lodash';
import { useIsMounted } from '@launch/hooks/useIsMounted';
const originalHeights = new WeakMap();
export const usePreviewIframe = ({ container, onLoad, ready, loadDelay }) => {
const isMounted = useIsMounted();
const [waitForIframe, setWaitForIframe] = useState(0);
const [iFrame, setIFrame] = useState(null);
const [maybeOk, setMaybeOk] = useState(false);
const isUpdating = useRef(false);
const updateCoverBlocks = useCallback((frame, cntnr) => {
if (!frame) return;
const ft = frame.getBoundingClientRect().top;
const ct = cntnr.getBoundingClientRect().top;
// If they have scrolled, don't mess with it
if (ft < ct) return;
isUpdating.current = true;
// WP scales the iframe to fit the container
// Get the scale value from the transform property
let scale = cntnr
.querySelector('[style*="scale"]')
?.style?.transform?.match(/scale\((.*?)\)/)?.[1];
scale = scale ? parseFloat(scale) : null;
// Get the height of the container and scale it
const cntnrHScaled = cntnr.offsetHeight / (scale ?? 1);
frame.style.setProperty('max-height', `${cntnrHScaled}px`, 'important');
const coverBlocks =
frame?.contentDocument?.querySelectorAll('.wp-block-cover');
for (const el of coverBlocks) {
if (!originalHeights.has(el)) {
// Cache the original 'vh' value
originalHeights.set(el, el.style.minHeight);
}
// Reapply the original 'vh' value so it can be used in computations
el.style.minHeight = originalHeights.get(el);
}
for (const el of coverBlocks) {
if (!frame.contentDocument?.defaultView) return;
// Get the computed height in px and use it for your calculation
const computedHeight = parseFloat(
frame.contentDocument.defaultView.getComputedStyle(el).height,
);
el.offsetHeight; // Force a reflow
el.style.minHeight =
computedHeight > 784 ? '784px' : computedHeight + 'px';
}
frame.style.setProperty('max-height', 'none', 'important');
isUpdating.current = false;
}, []);
useLayoutEffect(() => {
if (!ready) return;
// continuously check for iframe
const interval = setTimeout(() => {
const frame = container?.querySelector('iframe[title]');
// If not found, retry by updating state
if (!frame) return setWaitForIframe((prev) => prev + 1);
setIFrame(frame);
requestAnimationFrame(() => onLoad(frame, container));
}, 100);
return () => clearTimeout(interval);
}, [iFrame, ready, waitForIframe, container, onLoad]);
useLayoutEffect(() => {
setMaybeOk(false);
// After the iFrame is found, wait for it to load
// Note: using load event is not reliable
if (!iFrame?.contentDocument) return;
const observerConfig = {
attributes: false,
childList: true,
subtree: true,
};
const loaded = debounce(() => {
if (!isMounted.current || isUpdating.current) return;
// Allow the skeleton loader to be removed
setTimeout(() => setMaybeOk(true), loadDelay);
updateCoverBlocks(iFrame, container);
}, 50);
// Run once in case the iframe is already loaded
const firstRun = requestAnimationFrame(() => loaded(iFrame, container));
// Allow only for a max 2s wait time in case the mutation observer gets stuck
const longestWait = setTimeout(() => {
if (isMounted.current) {
m.disconnect();
loaded();
}
}, 2000);
// Continuously check for changes
const m = new MutationObserver(loaded);
m.observe(iFrame.contentDocument, observerConfig);
return () => {
cancelAnimationFrame(firstRun);
clearTimeout(longestWait);
loaded.cancel();
m?.disconnect();
};
}, [iFrame, container, isMounted, ready, updateCoverBlocks, loadDelay]);
return { loading: !iFrame, ready: maybeOk };
};