use polling over postMessage to detect when canvas is ready

This commit is contained in:
Oleg Isonen committed 2022-09-19 18:42:50 +03:00
1 parent b76ef631d0
commit d4e0d7d4f2
4 files changed
+15 -31

No files matched your search

@@ -1,9 +1,10 @@
import { useState } from "react";
import { useSubscribe } from "~/shared/pubsub";
import { publish, useSubscribe } from "~/shared/pubsub";
declare module "~/shared/pubsub" {
export interface PubsubMap {
designerReady: undefined;
designerReadyAck: undefined;
}
}
@@ -11,6 +12,7 @@ export const useSubscribeDesignerReady = () => {
const [isReady, setIsReady] = useState<boolean>(false);
useSubscribe("designerReady", () => {
setIsReady(true);
publish({ type: "designerReadyAck" });
});
return isReady;
};
+12 -12
View File
@@ -34,8 +34,8 @@ import {
import { useClientSettings } from "./shared/client-settings";
import { Navigator } from "./features/sidebar-left";
import { PANEL_WIDTH } from "./shared/constants";
import { onIframeLoad } from "~/shared/dom-utils";
import { Asset } from "@webstudio-is/asset-uploader";
import { useInterval } from "react-use";
export const links = () => {
return [
@@ -81,19 +81,20 @@ const useNavigatorLayout = () => {
};
const usePublishDesignerReady = (publish: Publish) => {
const [ref, setRef] = useState(null);
const [isAcknowledged, setIsAcknowledged] = useState(false);
useEffect(() => {
if (ref === null) return;
onIframeLoad(ref).then(() => {
useInterval(
() => {
// We publish this even to let canvas know that we are now listening to the events, otherwise if canvas loads faster than designer, which is possible with SSR,
// we can miss the events and designer will just not connect to the canvas.
publish({ type: "designerReady" });
});
}, [ref, publish]);
},
isAcknowledged ? null : 100
);
return setRef;
useSubscribe("designerReadyAck", () => {
setIsAcknowledged(true);
});
};
type SidePanelProps = {
@@ -255,16 +256,15 @@ export const Designer = ({ config, project }: DesignerProps) => {
const onRefReadCanvasWidth = useUpdateCanvasWidth();
const { onRef: onRefReadCanvas, onTransitionEnd } = useReadCanvasRect();
const [dragAndDropState] = useDragAndDropState();
const onRefIframeReady = usePublishDesignerReady(publish);
usePublishDesignerReady(publish);
const iframeRefCallback = useCallback(
(ref) => {
publishRef.current = ref;
onRefReadCanvasWidth(ref);
onRefReadCanvas(ref);
onRefIframeReady(ref);
},
[publishRef, onRefReadCanvasWidth, onRefReadCanvas, onRefIframeReady]
[publishRef, onRefReadCanvasWidth, onRefReadCanvas]
);
return (
@@ -1,2 +1 @@
export * from "./instance";
export * from "./on-iframe-load";
@@ -1,17 +0,0 @@
/**
* Resolve a promise when an iframe has readyState complete.
* Checks periodically for the readyState to be complete, because somttimes the load event may simply not fire for various reasons.
*/
export const onIframeLoad = (iframe: HTMLIFrameElement | null) =>
new Promise((resolve) => {
if (iframe === null) return;
const check = () => {
const document = iframe.contentDocument || iframe.contentWindow?.document;
if (document?.readyState === "complete") {
clearInterval(intervalId);
resolve("complete");
}
};
iframe.addEventListener("load", check);
const intervalId = setInterval(check, 100);
});