mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 14:03:33 +09:00
make sure we always catch the iframe when its fully loaded
This commit is contained in:
1 parent
589ca862f6
commit
6d359b878c
5 files changed
+41
-8
No files matched your search
@@ -46,7 +46,7 @@ import { usePublishScrollState } from "./shared/use-publish-scroll-state";
|
||||
import { useDragAndDrop } from "./shared/use-drag-drop";
|
||||
import { setInstanceChildrenMutable } from "~/shared/tree-utils";
|
||||
import { CanvasData } from "~/shared/db";
|
||||
import { useDesignerReady } from "./shared/use-designer-ready";
|
||||
import { useSubscribeDesignerReady } from "./shared/use-designer-ready";
|
||||
|
||||
registerContainers();
|
||||
|
||||
@@ -119,7 +119,7 @@ export const Canvas = ({ data }: CanvasProps): JSX.Element | null => {
|
||||
if (data.tree === null) {
|
||||
throw new Error("Tree is null");
|
||||
}
|
||||
const isDesignerReady = useDesignerReady();
|
||||
const isDesignerReady = useSubscribeDesignerReady();
|
||||
useInitializeBreakpoints(data.breakpoints);
|
||||
globalStyles();
|
||||
useAllUserProps(data.props);
|
||||
|
||||
@@ -7,7 +7,7 @@ declare module "~/shared/pubsub" {
|
||||
}
|
||||
}
|
||||
|
||||
export const useDesignerReady = () => {
|
||||
export const useSubscribeDesignerReady = () => {
|
||||
const [isReady, setIsReady] = useState<boolean>(false);
|
||||
useSubscribe("designerReady", () => {
|
||||
setIsReady(true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { type Publish, usePublish, useSubscribe } from "~/shared/pubsub";
|
||||
import type { Project } from "@webstudio-is/project";
|
||||
import type { Config } from "~/config";
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
import { useClientSettings } from "./shared/client-settings";
|
||||
import { Navigator } from "./features/sidebar-left";
|
||||
import { PANEL_WIDTH } from "./shared/constants";
|
||||
import { onLoad } from "~/shared/dom-utils";
|
||||
|
||||
export const links = () => {
|
||||
return [
|
||||
@@ -68,6 +69,22 @@ const useNavigatorLayout = () => {
|
||||
return isLoaded ? clientSettings.navigatorLayout : "docked";
|
||||
};
|
||||
|
||||
const usePublishDesignerReady = (publish: Publish) => {
|
||||
const [ref, setRef] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref === null) return;
|
||||
|
||||
onLoad(ref).then(() => {
|
||||
// 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]);
|
||||
|
||||
return setRef;
|
||||
};
|
||||
|
||||
type SidePanelProps = {
|
||||
children: JSX.Element | Array<JSX.Element>;
|
||||
isPreviewMode: boolean;
|
||||
@@ -226,17 +243,16 @@ export const Designer = ({ config, project }: DesignerProps) => {
|
||||
const onRefReadCanvasWidth = useUpdateCanvasWidth();
|
||||
const { onRef: onRefReadCanvas, onTransitionEnd } = useReadCanvasRect();
|
||||
const [dragAndDropState] = useDragAndDropState();
|
||||
const onRefIframeReady = usePublishDesignerReady(publish);
|
||||
|
||||
const iframeRefCallback = useCallback(
|
||||
(ref) => {
|
||||
publishRef.current = ref;
|
||||
onRefReadCanvasWidth(ref);
|
||||
onRefReadCanvas(ref);
|
||||
// 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" });
|
||||
onRefIframeReady(ref);
|
||||
},
|
||||
[publishRef, onRefReadCanvasWidth, onRefReadCanvas, publish]
|
||||
[publishRef, onRefReadCanvasWidth, onRefReadCanvas, onRefIframeReady]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from "./instance";
|
||||
export * from "./on-iframe-load";
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 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 onLoad = (iframe: HTMLIFrameElement) =>
|
||||
new Promise((resolve) => {
|
||||
if (iframe === null) return;
|
||||
const check = () => {
|
||||
if (document.readyState === "complete") {
|
||||
clearInterval(intervalId);
|
||||
resolve("complete");
|
||||
}
|
||||
};
|
||||
iframe.addEventListener("load", check);
|
||||
const intervalId = setInterval(check, 100);
|
||||
});
|
||||
Reference in new issue
Block a user