Something went wrong. Try again.
a tool for shared writing and social publishing
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869import { useCallback, useEffect, useRef } from "react";import { newMessagePortRpcSession } from "capnweb";import { PartsPageHost, PartsPageHandlers } from "src/partsPageChannel";
export function useIframeChannel(options: PartsPageHandlers) { let iframeElRef = useRef<HTMLIFrameElement | null>(null); let handlersRef = useRef(options); handlersRef.current = options;
let sessionRef = useRef<ReturnType< typeof newMessagePortRpcSession > | null>(null);
let cleanup = useCallback(() => { if (sessionRef.current) { sessionRef.current[Symbol.dispose](); sessionRef.current = null; } }, []);
let handleMessage = useCallback( (event: MessageEvent) => { let iframe = iframeElRef.current; if (!iframe?.contentWindow) return; if (event.source !== iframe.contentWindow) return; if (event.data?.type !== "parts.page.connect") return;
cleanup();
let { port1, port2 } = new MessageChannel();
let host = new PartsPageHost({ onOpen: (url) => handlersRef.current.onOpen(url), onReplaceWith: (block) => handlersRef.current.onReplaceWith(block), onAddBelow: (block) => handlersRef.current.onAddBelow(block), });
try { sessionRef.current = newMessagePortRpcSession(port1, host); } catch (e) { console.error("[parts.page] RPC session creation failed", e); throw e; }
iframe.contentWindow.postMessage({ type: "parts.page.channel" }, "*", [ port2, ]); }, [cleanup], );
useEffect(() => { window.addEventListener("message", handleMessage); return () => { window.removeEventListener("message", handleMessage); cleanup(); }; }, [handleMessage, cleanup]);
let iframeRef = useCallback( (el: HTMLIFrameElement | null) => { iframeElRef.current = el; }, [], );
return { iframeRef };}