import { Link } from "@tanstack/react-router";
import { useEffect, useRef, useState } from "react";
import { mintEditorSession } from "~/fns/editor";
type Committed = { sha: string; branch: string; pullUrl: string | null };
const FRAME_SANDBOX = "allow-scripts allow-modals";
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
function committedResult(data: Record<string, unknown>): Committed | null {
const result = data.result;
if (!isRecord(result) || typeof result.sha !== "string" || typeof result.branch !== "string") return null;
return {
sha: result.sha,
branch: result.branch,
pullUrl: typeof result.pullUrl === "string" ? result.pullUrl : null,
};
}
/**
* Hosts the workspace editor in a sandboxed, opaque-origin iframe. The frame never sees session cookies:
* this page mints a ref-scoped token and hands it over with postMessage once the frame says it's ready.
*/
export function WorkspaceEditor({ owner, repo, gitRef }: { owner: string; repo: string; gitRef: string }) {
const frame = useRef<HTMLIFrameElement>(null);
const [error, setError] = useState<string | null>(null);
const [committed, setCommitted] = useState<Committed | null>(null);
useEffect(() => {
let handedOver = false;
async function onMessage(event: MessageEvent) {
const target = frame.current?.contentWindow;
const message: unknown = event.data;
if (!target || event.source !== target || event.origin !== "null" || !isRecord(message)) return;
if (message.type === "gitfor-editor:ready" && !handedOver) {
handedOver = true;
try {