import React, { useMemo, useSyncExternalStore } from "react"; import type { AppManifest } from "../kernel/types"; import { makeOSApi } from "../kernel/sdk"; import { AppErrorBoundary, getCompiled, } from "../kernel/appRuntime"; import { onRuntimeVersionChange, runtimeVersionOf } from "../kernel/store"; // Renders a single app instance inside a window body. // Built-in apps render their component directly; generated apps are compiled. export function AppHost({ app, windowId }: { app: AppManifest; windowId: string }) { const version = useSyncExternalStore( onRuntimeVersionChange, () => runtimeVersionOf(app.id) ); const os = useMemo(() => makeOSApi(app.id, windowId), [app.id, windowId]); // Only meaningful for generated apps; cheap no-op for built-ins (cached). const compiled = useMemo( () => (app.builtin ? null : getCompiled(app, version)), [app, version] ); if (app.builtin && app.component) { const C = app.component; return ( ); } // generated app if (!compiled) return null; if (compiled.error) { return ( ); } const Generated = compiled.Component!; return ( ); } function CompileError({ message }: { message: string }): React.ReactElement { // Thrown so the error boundary picks it up and offers self-heal. throw new Error("Compile error: " + message); }