mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:10:45 +00:00
73 lines
2.6 KiB
TypeScript
73 lines
2.6 KiB
TypeScript
import { lowercasePreservingWhitespace } from "../shared/string-coerce.js";
|
|
|
|
export const A2UI_PATH = "/__openclaw__/a2ui";
|
|
|
|
export const CANVAS_HOST_PATH = "/__openclaw__/canvas";
|
|
|
|
export const CANVAS_WS_PATH = "/__openclaw__/ws";
|
|
|
|
export function isA2uiPath(pathname: string): boolean {
|
|
return pathname === A2UI_PATH || pathname.startsWith(`${A2UI_PATH}/`);
|
|
}
|
|
|
|
export function injectCanvasLiveReload(html: string): string {
|
|
const snippet = `
|
|
<script>
|
|
(() => {
|
|
// Cross-platform action bridge helper.
|
|
// Works on:
|
|
// - iOS: window.webkit.messageHandlers.openclawCanvasA2UIAction.postMessage(...)
|
|
// - Android: window.openclawCanvasA2UIAction.postMessage(...)
|
|
const handlerNames = ["openclawCanvasA2UIAction"];
|
|
function postToNode(payload) {
|
|
try {
|
|
const raw = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
for (const name of handlerNames) {
|
|
const iosHandler = globalThis.webkit?.messageHandlers?.[name];
|
|
if (iosHandler && typeof iosHandler.postMessage === "function") {
|
|
iosHandler.postMessage(raw);
|
|
return true;
|
|
}
|
|
const androidHandler = globalThis[name];
|
|
if (androidHandler && typeof androidHandler.postMessage === "function") {
|
|
// Important: call as a method on the interface object (binding matters on Android WebView).
|
|
androidHandler.postMessage(raw);
|
|
return true;
|
|
}
|
|
}
|
|
} catch {}
|
|
return false;
|
|
}
|
|
function sendUserAction(userAction) {
|
|
const id =
|
|
(userAction && typeof userAction.id === "string" && userAction.id.trim()) ||
|
|
(globalThis.crypto?.randomUUID?.() ?? String(Date.now()));
|
|
const action = { ...userAction, id };
|
|
return postToNode({ userAction: action });
|
|
}
|
|
globalThis.OpenClaw = globalThis.OpenClaw ?? {};
|
|
globalThis.OpenClaw.postMessage = postToNode;
|
|
globalThis.OpenClaw.sendUserAction = sendUserAction;
|
|
globalThis.openclawPostMessage = postToNode;
|
|
globalThis.openclawSendUserAction = sendUserAction;
|
|
|
|
try {
|
|
const cap = new URLSearchParams(location.search).get("oc_cap");
|
|
const proto = location.protocol === "https:" ? "wss" : "ws";
|
|
const capQuery = cap ? "?oc_cap=" + encodeURIComponent(cap) : "";
|
|
const ws = new WebSocket(proto + "://" + location.host + ${JSON.stringify(CANVAS_WS_PATH)} + capQuery);
|
|
ws.onmessage = (ev) => {
|
|
if (String(ev.data || "") === "reload") location.reload();
|
|
};
|
|
} catch {}
|
|
})();
|
|
</script>
|
|
`.trim();
|
|
|
|
const idx = lowercasePreservingWhitespace(html).lastIndexOf("</body>");
|
|
if (idx >= 0) {
|
|
return `${html.slice(0, idx)}\n${snippet}\n${html.slice(idx)}`;
|
|
}
|
|
return `${html}\n${snippet}\n`;
|
|
}
|