89 lines
3.5 KiB
JavaScript
89 lines
3.5 KiB
JavaScript
import { KvList } from "./KvList";
|
|
|
|
function formatNumber(value, digits = 3) {
|
|
return Number(value ?? 0).toFixed(digits);
|
|
}
|
|
|
|
function formatEndpoint(endpoint) {
|
|
const backend = endpoint?.backend || "none";
|
|
const device = endpoint?.device ? ` ${endpoint.device}` : "";
|
|
return `${backend}${device}`;
|
|
}
|
|
|
|
function formatVideoMode(endpoint) {
|
|
const resolution = endpoint?.resolution || "Unknown";
|
|
const frameRate = endpoint?.frameRate ? ` ${endpoint.frameRate}` : "";
|
|
return `${resolution}${frameRate}`;
|
|
}
|
|
|
|
export function StatusPanels({ app, performance, runtime, video, videoOutput }) {
|
|
const budgetUsedPercent = Math.max(0, Math.min(100, Number(performance.budgetUsedPercent) || 0));
|
|
const outputEnabled = Boolean(videoOutput?.enabled);
|
|
|
|
return (
|
|
<>
|
|
<div className="panel panel--telemetry">
|
|
<div className="telemetry-header">
|
|
<h3>Status</h3>
|
|
<div className="status-badges" aria-label="Current status">
|
|
<span className={`mini-status${runtime.compileSucceeded ? " mini-status--ready" : " mini-status--error"}`}>
|
|
{runtime.compileSucceeded ? "Ready" : "Error"}
|
|
</span>
|
|
<span className={`mini-status${outputEnabled ? " mini-status--ready" : " mini-status--error"}`}>
|
|
{outputEnabled ? "Output" : "No output"}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="telemetry-sections">
|
|
<section className="telemetry-section" aria-labelledby="runtime-status-heading">
|
|
<h4 id="runtime-status-heading">Runtime</h4>
|
|
<KvList
|
|
variant="rows"
|
|
values={[
|
|
["Layers", `${runtime.layerCount || 0}`],
|
|
["Auto reload", app.autoReload ? "On" : "Off"],
|
|
["Temporal cap", `${app.maxTemporalHistoryFrames ?? 0}`],
|
|
["Control URL", `127.0.0.1:${app.serverPort}`],
|
|
["Render", `${formatNumber(performance.renderMs, 2)} ms`],
|
|
["Smoothed", `${formatNumber(performance.smoothedRenderMs, 2)} ms`],
|
|
["Frame budget", `${formatNumber(performance.frameBudgetMs, 2)} ms`],
|
|
]}
|
|
/>
|
|
<div className="meter-row">
|
|
<span>Budget used</span>
|
|
<div className="progress-track" aria-hidden="true">
|
|
<div className="progress-bar" style={{ width: `${budgetUsedPercent}%` }} />
|
|
</div>
|
|
<strong>{formatNumber(performance.budgetUsedPercent, 1)}%</strong>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="telemetry-section" aria-labelledby="video-status-heading">
|
|
<h4 id="video-status-heading">Video</h4>
|
|
<KvList
|
|
variant="rows"
|
|
values={[
|
|
["Input", formatEndpoint(app.input)],
|
|
["Input mode", formatVideoMode(app.input)],
|
|
["Output", formatEndpoint(app.output)],
|
|
["Output mode", formatVideoMode(app.output)],
|
|
["Output size", `${video.width || 0} x ${video.height || 0}`],
|
|
["Output status", videoOutput?.statusMessage || "Unknown"],
|
|
["Schedule failures", `${videoOutput?.scheduleFailures ?? 0}`],
|
|
]}
|
|
/>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="panel panel--compiler">
|
|
<h3>Compiler</h3>
|
|
<pre className="log-panel" aria-live="polite">
|
|
{runtime.compileMessage || "No compiler output."}
|
|
</pre>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|