import { useEffect, useState } from "react"; import { LayerStack } from "./components/LayerStack"; import { StackPresetToolbar } from "./components/StackPresetToolbar"; import { StatusPanels } from "./components/StatusPanels"; import { useRuntimeState } from "./hooks/useRuntimeState"; function App() { const [appState, setAppState] = useRuntimeState(); const [pendingShaderId, setPendingShaderId] = useState(""); const [presetName, setPresetName] = useState(""); const [selectedPresetName, setSelectedPresetName] = useState(""); const [expandedLayerIds, setExpandedLayerIds] = useState([]); const [dragLayerId, setDragLayerId] = useState(null); const [dropTargetLayerId, setDropTargetLayerId] = useState(null); const layers = appState?.layers ?? []; const shaders = appState?.shaders ?? []; const performance = appState?.performance ?? {}; const runtime = appState?.runtime ?? {}; const video = appState?.video ?? {}; const app = appState?.app ?? {}; const stackPresets = appState?.stackPresets ?? []; useEffect(() => { if (!pendingShaderId && shaders.length > 0) { setPendingShaderId(shaders[0].id); } else if (pendingShaderId && !shaders.some((shader) => shader.id === pendingShaderId)) { setPendingShaderId(shaders[0]?.id ?? ""); } }, [pendingShaderId, shaders]); useEffect(() => { if (!selectedPresetName && stackPresets.length > 0) { setSelectedPresetName(stackPresets[0]); } else if (selectedPresetName && !stackPresets.includes(selectedPresetName)) { setSelectedPresetName(stackPresets[0] ?? ""); } }, [selectedPresetName, stackPresets]); useEffect(() => { const layerIds = new Set(layers.map((layer) => layer.id)); setExpandedLayerIds((current) => current.filter((layerId) => layerIds.has(layerId))); }, [layers]); if (!appState) { return (

Loading

Waiting for control state from the native host.

); } return (

Video Shader Toys

Live shader stack, DeckLink status, and runtime controls.

{runtime.compileSucceeded ? "Ready" : "Compile Error"}
Shaders
{shaders.length}
Layers
{layers.length}
Signal
{video.hasSignal ? "Present" : "Missing"}
Render
{Number(performance.renderMs ?? 0).toFixed(2)} ms
); } export default App;