mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
use polling over postMessage to detect when canvas is ready
This commit is contained in:
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;
|
||||
};
|
||||
@@ -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);
|
||||
});
|
||||
Reference in new issue
Block a user