Files
FreeCADWasmDev/web/src/web-window-host-bridge.ts
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

62 lines
3.8 KiB
TypeScript

import { createFailure, createSuccess, type FacadeResponse } from "./facade-envelope.js";
import type { WebModuleRouter } from "./module-router.js";
import { viewEndpoint, type ViewOwner } from "./part-view-facade.js";
export type WindowPanel = { objectName: string; title: string; visible: boolean; enabled?: boolean };
export type WindowLayout = {
windows: Array<{ documentId: string; label: string }>;
columns: number; rows: number; activeDocument: string | null;
};
export type WindowHostResult = Partial<WindowLayout> & {
command: string; documentId: string; items?: WindowPanel[]; locked?: boolean;
};
type Host = {
snapshot(): { panels: WindowPanel[]; toolbar: string };
apply(value: WindowHostResult, owner: ViewOwner): void;
};
let host: Host | undefined;
export function registerWebWindowHost(value: Host) {
host = value;
return () => { if (host === value) host = undefined; };
}
export function executeWebWindowHost(router: WebModuleRouter, command: string,
args: Record<string, unknown>, documentId: string): Promise<FacadeResponse> | undefined {
if (!["Std_DockViewMenu", "Std_TileWindows", "Std_ToggleToolBarLock"].includes(command)) return;
const mounted = host;
if (!mounted) return Promise.resolve(createFailure("desktop-Web", "window_host_unavailable", "The workbench window host is not mounted"));
const owner = args.runtimeOwner ?? "PartBox";
if (owner !== "PartBox" && owner !== "DocumentProbe")
return Promise.resolve(createFailure("desktop-Web", "wrong_document_owner", "Select the document's native runtime"));
if (!documentId.trim() || (args.documentId !== undefined && args.documentId !== documentId))
return Promise.resolve(createFailure("desktop-Web", "document_mismatch", "Command document identifiers differ"));
return router.request("Part", viewEndpoint(owner), {
schema: "freecad-web/document-view/v1", owner, document: documentId, command,
parameters: { ...args, documentId, host: mounted.snapshot() },
}, documentId).then(response => {
if (response.kind !== "result") return response;
const value = response.result as WindowHostResult;
if (!value || value.command !== command || value.documentId !== documentId)
return createFailure(response.requestId, "native_protocol_error", "Window response identity mismatch");
if (command === "Std_DockViewMenu" && (!Array.isArray(value.items)
|| value.items.some(item => !item || typeof item.objectName !== "string" || typeof item.title !== "string"
|| typeof item.visible !== "boolean" || typeof item.enabled !== "boolean")))
return createFailure(response.requestId, "native_protocol_error", "Invalid native dock actions");
if (command === "Std_ToggleToolBarLock" && typeof value.locked !== "boolean")
return createFailure(response.requestId, "native_protocol_error", "Invalid native toolbar lock state");
if (command === "Std_TileWindows" && (!Array.isArray(value.windows) || !value.windows.length
|| value.windows.some(item => !item || typeof item.documentId !== "string" || !item.documentId || typeof item.label !== "string")
|| !Number.isInteger(value.columns) || (value.columns ?? 0) < 1
|| !Number.isInteger(value.rows) || (value.rows ?? 0) < 1
|| !(value.activeDocument === null || typeof value.activeDocument === "string")))
return createFailure(response.requestId, "native_protocol_error", "Invalid native window layout");
if (host !== mounted)
return createFailure(response.requestId, "window_host_unavailable", "The workbench window host changed during the command");
mounted.apply(value, owner);
return createSuccess(response.requestId, {
schema: "freecad-web/document-view-batch/v1", owner, documentId,
records: [{ apiId: `Web:desktop:${command}`, name: command, status: "success", native: true, result: value }], count: 1,
});
});
}