Spaces:
Paused
Paused
| import React, { useRef, useEffect } from "react"; | |
| import { useAppDispatch } from "../../store/hook"; | |
| import { update_logs } from "../../store/features/editorSlice"; | |
| import { getCompileCode } from "../../store/features/compilerSlice"; | |
| import { createIframeContent } from "../../utils/createIframeContent"; | |
| import { IframeLoaderScreen } from "./IframeLoaderScreen"; | |
| import { IframeErrorScreen } from "./IframeErrorScreen"; | |
| import { LanguagesInterface } from "../../_types/editorTypes"; | |
| import { CompilerOutput, CompilerStatus } from "../../_types/compilerTypes"; | |
| interface IframeProps { | |
| tabs: LanguagesInterface; | |
| output: CompilerOutput; | |
| isCompiling: boolean; | |
| esbuildStatus: CompilerStatus; | |
| } | |
| const IframePanel = ({ | |
| tabs, | |
| output, | |
| isCompiling, | |
| esbuildStatus, | |
| }: IframeProps) => { | |
| const iframe = useRef<any>(); | |
| const dispatch = useAppDispatch(); | |
| const htmlFrameContent = createIframeContent(tabs.css?.data, tabs.html?.data); | |
| //=== incoming message | |
| useEffect(() => { | |
| window.onmessage = function (response: MessageEvent) { | |
| if (response.data && response.data.source === "iframe") { | |
| let errorObject = { | |
| method: "error", | |
| id: Date.now(), | |
| data: [`${response.data.message}`], | |
| }; | |
| dispatch(update_logs(errorObject)); | |
| } | |
| }; | |
| if (tabs.javascript && esbuildStatus.isReady) { | |
| setTimeout(async () => { | |
| dispatch( | |
| getCompileCode(tabs.javascript.data, tabs.javascript.entryPoints) | |
| ); | |
| }, 50); | |
| } | |
| }, [dispatch, tabs, esbuildStatus.isReady]); | |
| //=== outgoing massage | |
| useEffect(() => { | |
| iframe.current.srcdoc = htmlFrameContent; | |
| setTimeout(async () => { | |
| iframe?.current?.contentWindow?.postMessage(output.code, "*"); | |
| }, 40); | |
| }, [htmlFrameContent, output]); | |
| return ( | |
| <div className="iframe-container"> | |
| {/* build error */} | |
| {output.error ? <IframeErrorScreen err={output.error} /> : ""} | |
| {/* Loading screen */} | |
| {isCompiling ? ( | |
| <div className="absolute h-full w-full bg-gray-50 z-40"> | |
| <IframeLoaderScreen /> | |
| </div> | |
| ) : ( | |
| "" | |
| )} | |
| <iframe | |
| id="super-iframe" | |
| sandbox="allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation" | |
| allow="accelerometer; camera; encrypted-media; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write" | |
| scrolling="auto" | |
| frameBorder="0" | |
| ref={iframe} | |
| title="previewWindow" | |
| srcDoc={htmlFrameContent} | |
| onLoad={async () => { | |
| const Hook = (await import("console-feed")).Hook; | |
| Hook( | |
| iframe.current.contentWindow.console, | |
| (log) => { | |
| dispatch(update_logs(log)); | |
| }, | |
| false | |
| ); | |
| }} | |
| /> | |
| </div> | |
| ); | |
| }; | |
| const Iframe = React.memo(IframePanel); | |
| export default Iframe; | |