multichannel support + colormap inherit

This commit is contained in:
2026-03-24 21:01:58 -07:00
parent 53e2fc7746
commit a60b0c15ca
12 changed files with 889 additions and 220 deletions

View File

@@ -436,6 +436,9 @@ function Flow() {
case 'overlay':
updateNodeData(msg.data.node_id, { overlay: msg.data.overlay });
break;
case 'node_warning':
updateNodeData(msg.data.node_id, { warning: msg.data.message });
break;
}
});
api.initWS();
@@ -500,9 +503,36 @@ function Flow() {
data: {
...n.data,
widgetValues: { ...n.data.widgetValues, [name]: value },
// Clear warning when user changes a value
warning: null,
},
};
}));
// If this is a filename/name change on a LoadFile/LoadDemo node, fetch channels
if ((name === 'filename' || name === 'name') && value) {
const node = reactFlow.getNode(nodeId);
if (node && (node.data.className === 'LoadFile' || node.data.className === 'LoadDemo')) {
api.getChannels(value).then((channels) => {
setNodes((prev) => prev.map((n) => {
if (n.id !== nodeId) return n;
return {
...n,
data: {
...n.data,
definition: {
...n.data.definition,
output: channels.map((c) => c.type),
output_name: channels.map((c) => c.name),
},
},
};
}));
reactFlow.updateNodeInternals(nodeId);
});
}
}
scheduleAutoRun();
}, [setNodes]); // scheduleAutoRun is stable (no deps)
@@ -568,6 +598,27 @@ function Flow() {
setNodes((ns) => [...ns, newNode]);
// For LoadFile/LoadDemo, auto-fetch channels for the default value
if (className === 'LoadDemo' && widgetValues.name) {
api.getChannels(widgetValues.name).then((channels) => {
setNodes((prev) => prev.map((n) => {
if (n.id !== newNodeId) return n;
return {
...n,
data: {
...n.data,
definition: {
...n.data.definition,
output: channels.map((c) => c.type),
output_name: channels.map((c) => c.name),
},
},
};
}));
reactFlow.updateNodeInternals(newNodeId);
});
}
// Auto-connect if this was triggered by dropping a connection on blank space
if (contextMenu.pendingHandleId) {
const filterType = contextMenu.filterType;

View File

@@ -211,6 +211,11 @@ function CustomNode({ id, data }) {
);
})}
{/* Warning notification */}
{data.warning && (
<div className="node-warning">{data.warning}</div>
)}
{/* Widget rows */}
{widgets.map((w) => (
<div className="widget-row" key={w.name}>

View File

@@ -34,6 +34,12 @@ export async function uploadFile(file) {
return r.json();
}
export async function getChannels(filepath) {
const r = await fetch(`/channels?file=${encodeURIComponent(filepath)}`);
if (!r.ok) return [{ name: 'field', type: 'DATA_FIELD' }];
return r.json();
}
export async function runPrompt(prompt) {
const r = await fetch('/prompt', {
method: 'POST',

View File

@@ -82,10 +82,7 @@ html, body, #root {
padding: 4px 10px;
border-radius: 4px;
font-size: 11px;
max-width: 400px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 60%;
flex-shrink: 1;
}
.status-bar.info { color: #90caf9; }
@@ -155,6 +152,15 @@ html, body, #root {
padding: 4px 0;
}
.node-warning {
padding: 3px 10px;
font-size: 10px;
color: #fbbf24;
background: rgba(251, 191, 36, 0.1);
border-top: 1px solid rgba(251, 191, 36, 0.2);
border-bottom: 1px solid rgba(251, 191, 36, 0.2);
}
/* ── I/O rows ──────────────────────────────────────────────────────── */
.io-row {
display: flex;

View File

@@ -9,6 +9,7 @@ export default defineConfig({
'/nodes': 'http://127.0.0.1:8188',
'/files': 'http://127.0.0.1:8188',
'/browse': 'http://127.0.0.1:8188',
'/channels': 'http://127.0.0.1:8188',
'/upload': 'http://127.0.0.1:8188',
'/download': 'http://127.0.0.1:8188',
'/prompt': 'http://127.0.0.1:8188',