159 lines
4.7 KiB
JavaScript
159 lines
4.7 KiB
JavaScript
import { findWidget, hideWidget, hideWidgetInput } from "./utils.js";
|
|
import { ButtonRowWidget } from "./widgets/button_row_widget.js";
|
|
import { PresetRowWidget } from "./widgets/preset_row_widget.js";
|
|
|
|
// --- Helpers ---
|
|
|
|
const loadPresets = (node, key) => {
|
|
const w = findWidget(node, key);
|
|
if (!w?.value) return {};
|
|
try {
|
|
return JSON.parse(w.value);
|
|
} catch {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
const savePresets = (node, key, data) => {
|
|
const w = findWidget(node, key);
|
|
const sorted = Object.fromEntries(
|
|
Object.entries(data).sort(([a], [b]) => a.localeCompare(b)),
|
|
);
|
|
if (w) w.value = JSON.stringify(sorted);
|
|
};
|
|
|
|
const getPresetNames = (data) => Object.keys(data).sort();
|
|
|
|
// --- Factory ---
|
|
|
|
export const createPresetManager = (
|
|
node,
|
|
{
|
|
presetDataKey = "preset_data",
|
|
onCapture,
|
|
onRecall,
|
|
nodeLabel = "Node",
|
|
} = {},
|
|
) => {
|
|
const presetDataWidget = findWidget(node, presetDataKey);
|
|
|
|
let presetRow = null;
|
|
|
|
const handleNew = () => {
|
|
const name = prompt("New preset name:");
|
|
if (!name?.trim()) return;
|
|
|
|
const data = loadPresets(node, presetDataKey);
|
|
if (data[name.trim()]) {
|
|
alert(`[${nodeLabel}] Preset "${name.trim()}" already exists.`);
|
|
return;
|
|
}
|
|
try {
|
|
data[name.trim()] = onCapture();
|
|
} catch (e) {
|
|
alert(`[${nodeLabel}] ${e.message}`);
|
|
return;
|
|
}
|
|
|
|
savePresets(node, presetDataKey, data);
|
|
presetRow.setPresets(getPresetNames(data));
|
|
presetRow.value = name.trim();
|
|
presetRow.flashSave(node);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const handleSave = () => {
|
|
if (!presetRow || presetRow.isEmpty()) return;
|
|
|
|
const data = loadPresets(node, presetDataKey);
|
|
data[presetRow.value] = onCapture();
|
|
savePresets(node, presetDataKey, data);
|
|
presetRow.flashSave(node);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const handleDelete = () => {
|
|
if (!presetRow || presetRow.isEmpty()) return;
|
|
if (!confirm(`Delete preset "${presetRow.value}"?`)) return;
|
|
|
|
const data = loadPresets(node, presetDataKey);
|
|
delete data[presetRow.value];
|
|
savePresets(node, presetDataKey, data);
|
|
presetRow.setPresets(getPresetNames(data));
|
|
if (!presetRow.isEmpty()) handleSelect(presetRow.value);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const handleSelect = (name) => {
|
|
const data = loadPresets(node, presetDataKey);
|
|
const state = data[name];
|
|
if (!state) return;
|
|
onRecall(state);
|
|
};
|
|
|
|
const handleExport = () => {
|
|
const data = loadPresets(node, presetDataKey);
|
|
if (!Object.keys(data).length) {
|
|
alert(`[${nodeLabel}] No presets to export.`);
|
|
return;
|
|
}
|
|
|
|
const json = JSON.stringify(data, null, 2);
|
|
navigator.clipboard
|
|
.writeText(json)
|
|
.then(() => {
|
|
alert(`[${nodeLabel}] Presets copied to clipboard.`);
|
|
})
|
|
// Fallback if clipboard unavailable
|
|
.catch(() => prompt("Copy this JSON:", json));
|
|
};
|
|
|
|
const handleImport = () => {
|
|
const json = prompt("Paste preset JSON:");
|
|
if (!json?.trim()) return;
|
|
try {
|
|
const data = JSON.parse(json);
|
|
if (typeof data !== "object" || Array.isArray(data)) {
|
|
alert(`[${nodeLabel}] Invalid format.`);
|
|
return;
|
|
}
|
|
|
|
savePresets(node, presetDataKey, data);
|
|
presetRow.setPresets(getPresetNames(data));
|
|
if (!presetRow.isEmpty()) handleSelect(presetRow.value);
|
|
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
} catch (e) {
|
|
alert(`[${nodeLabel}] Invalid JSON.`);
|
|
console.warn(`[${nodeLabel}] Error during import`, e);
|
|
}
|
|
};
|
|
|
|
presetRow = new PresetRowWidget(
|
|
"preset_row",
|
|
handleNew,
|
|
handleSave,
|
|
handleDelete,
|
|
handleSelect,
|
|
);
|
|
|
|
const exportImportRow = new ButtonRowWidget("preset_actions", [
|
|
{ label: "📋 Export", onClick: handleExport },
|
|
{ label: "📥 Import", onClick: handleImport },
|
|
]);
|
|
|
|
// Initialize presets from stored data
|
|
if (presetDataWidget) {
|
|
hideWidget(presetDataWidget, true);
|
|
hideWidgetInput(node, presetDataWidget);
|
|
const data = loadPresets(node, presetDataKey);
|
|
presetRow.setPresets(getPresetNames(data));
|
|
if (node.graph) node.graph.setDirtyCanvas(true, true);
|
|
}
|
|
|
|
return { presetRow, exportImportRow };
|
|
};
|