2024-07-28 23:03:32 +08:00
|
|
|
import { useEffect, useRef } from "preact/hooks";
|
2024-07-30 23:33:33 +08:00
|
|
|
import type { Client } from "../client.ts";
|
2024-08-07 02:11:38 +08:00
|
|
|
import type { PanelConfig } from "../type.ts";
|
2023-10-03 20:16:33 +08:00
|
|
|
import { panelHtml } from "./panel_html.ts";
|
2022-10-10 20:50:21 +08:00
|
|
|
|
|
|
|
export function Panel({
|
|
|
|
config,
|
|
|
|
editor,
|
|
|
|
}: {
|
|
|
|
config: PanelConfig;
|
2023-07-14 22:56:20 +08:00
|
|
|
editor: Client;
|
2022-10-10 20:50:21 +08:00
|
|
|
}) {
|
|
|
|
const iFrameRef = useRef<HTMLIFrameElement>(null);
|
2024-06-07 14:19:26 +08:00
|
|
|
|
|
|
|
function updateContent() {
|
|
|
|
if (!iFrameRef.current?.contentWindow) {
|
2022-10-10 20:50:21 +08:00
|
|
|
return;
|
|
|
|
}
|
2024-06-07 14:19:26 +08:00
|
|
|
|
|
|
|
iFrameRef.current.contentWindow.postMessage({
|
|
|
|
type: "html",
|
|
|
|
html: config.html,
|
|
|
|
script: config.script,
|
2024-08-02 23:14:40 +08:00
|
|
|
theme: document.getElementsByTagName("html")[0].dataset.theme,
|
2024-06-07 14:19:26 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-10-10 20:50:21 +08:00
|
|
|
const iframe = iFrameRef.current;
|
2024-06-07 14:19:26 +08:00
|
|
|
if (!iframe) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-08-02 23:14:40 +08:00
|
|
|
iframe.addEventListener("load", updateContent);
|
2024-06-07 14:19:26 +08:00
|
|
|
updateContent();
|
|
|
|
|
2022-10-10 20:50:21 +08:00
|
|
|
return () => {
|
2024-06-07 14:19:26 +08:00
|
|
|
iframe.removeEventListener("load", updateContent);
|
2022-10-10 20:50:21 +08:00
|
|
|
};
|
|
|
|
}, [config.html, config.script]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const messageListener = (evt: any) => {
|
|
|
|
if (evt.source !== iFrameRef.current!.contentWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const data = evt.data;
|
|
|
|
if (!data) {
|
|
|
|
return;
|
|
|
|
}
|
2023-01-16 17:40:16 +08:00
|
|
|
switch (data.type) {
|
|
|
|
case "event":
|
|
|
|
editor.dispatchAppEvent(data.name, ...data.args);
|
|
|
|
break;
|
|
|
|
case "syscall": {
|
|
|
|
const { id, name, args } = data;
|
2024-02-07 21:50:01 +08:00
|
|
|
editor.clientSystem.localSyscall(name, args).then(
|
2023-07-14 19:44:30 +08:00
|
|
|
(result) => {
|
|
|
|
if (!iFrameRef.current?.contentWindow) {
|
|
|
|
// iFrame already went away
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
iFrameRef.current!.contentWindow!.postMessage({
|
|
|
|
type: "syscall-response",
|
|
|
|
id,
|
|
|
|
result,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
).catch((e: any) => {
|
2023-01-16 18:06:07 +08:00
|
|
|
if (!iFrameRef.current?.contentWindow) {
|
|
|
|
// iFrame already went away
|
|
|
|
return;
|
|
|
|
}
|
2023-01-16 17:40:16 +08:00
|
|
|
iFrameRef.current!.contentWindow!.postMessage({
|
|
|
|
type: "syscall-response",
|
|
|
|
id,
|
|
|
|
error: e.message,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
2022-10-10 20:50:21 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
globalThis.addEventListener("message", messageListener);
|
|
|
|
return () => {
|
|
|
|
globalThis.removeEventListener("message", messageListener);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="sb-panel" style={{ flex: config.mode }}>
|
2024-08-02 23:14:40 +08:00
|
|
|
<iframe
|
|
|
|
srcDoc={panelHtml}
|
|
|
|
ref={iFrameRef}
|
|
|
|
style={{ visibility: "hidden" }}
|
|
|
|
onLoad={() => iFrameRef.current!.style.visibility = "visible"}
|
|
|
|
/>
|
2022-10-10 20:50:21 +08:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|