|
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); |
|
|
|
|
|
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]); |
|
|
|
|
|
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; |
|
|