Update rs_bypass.js

This commit is contained in:
Rayko
2026-09-10 11:44:11 +03:00
committed by GitHub
parent 07785264d7
commit 04ae215b65
+201 -168
View File
@@ -27,10 +27,9 @@ app.registerExtension({
const result = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
const self = this;
// Новая структура данных: храним объекты { id, enabled }
self.data = {
bypassedNodes: [], // массив { id, enabled }
bypassedGroups: [], // массив { id, enabled }
bypassedNodes: [],
bypassedGroups: [],
menuSearch: "",
expandedGroups: {},
menuOpen: false,
@@ -41,7 +40,7 @@ app.registerExtension({
self.padding = 10;
self.clickZones = [];
self._lastBypassedCount = -1;
self._lastSyncTimestamp = 0; // для ограничения частоты синхронизации
self._lastSyncTimestamp = 0;
const stateWidget = self.widgets.find(w => w.name === "bypass_state");
const isNewNode = !stateWidget.value || stateWidget.value === "{}";
@@ -62,7 +61,6 @@ app.registerExtension({
try {
const savedData = JSON.parse(stateWidget.value || "{}");
if (savedData && typeof savedData === 'object') {
// Преобразуем старые форматы (массивы id) в новый формат
if (Array.isArray(savedData.nodes)) {
if (savedData.nodes.length && typeof savedData.nodes[0] === 'number') {
self.data.bypassedNodes = savedData.nodes.map(id => ({ id, enabled: true }));
@@ -130,8 +128,8 @@ app.registerExtension({
};
self.drawToggle = function(ctx, isOn, x, y, w, h) {
const toggleW = 36;
const toggleH = 18;
const toggleW = 28;
const toggleH = 15;
const toggleX = x;
const toggleY = y + (h - toggleH) / 2;
const radius = toggleH / 2;
@@ -153,28 +151,55 @@ app.registerExtension({
self.drawBypassedItem = function(ctx, title, x, y, w, h, index, isBypassed) {
const toggleZone = self.drawToggle(ctx, isBypassed, x, y, 36, h);
const textX = x + 44;
const textW = w - 64;
ctx.fillStyle = index % 2 === 0 ? "rgba(255,68,68,0.1)" : "rgba(255,68,68,0.05)";
ctx.fillRect(textX, y, textW, h);
const pad = 8;
const removeW = 16;
const gap = 8;
const textX = x + 28 + pad;
const removeX = x + w - removeW + 4;
const textW = removeX - gap - textX;
const bgHeight = 20;
const bgRadius = 4;
const bgY = y + (h - bgHeight) / 2;
ctx.fillStyle = index % 2 === 0 ? "rgba(34,34,34,1)" : "rgba(34,34,34,0.5)";
ctx.beginPath();
ctx.roundRect(textX, bgY, textW, bgHeight, bgRadius);
ctx.fill();
ctx.fillStyle = "#ff4444";
ctx.font = "11px sans-serif";
ctx.textAlign = "left";
ctx.fillText(title, textX + 8, y + h/2 + 4);
ctx.fillText(title, textX + pad, y + h/2 + 4);
ctx.fillStyle = "#ff6666";
ctx.fillText("✕", textX + textW - 12, y + h/2 + 4);
ctx.textAlign = "center";
ctx.fillText("✕", removeX + removeW / 2, y + h/2 + 4);
return {
toggle: toggleZone,
remove: { x: removeX, y: y, w: removeW, h: h }
};
};
self._rs_syncToggleAllState = function() {
const allItems = [...self.data.bypassedGroups, ...self.data.bypassedNodes];
if (allItems.length === 0) return;
return { toggle: toggleZone, remove: { x: textX + textW - 20, y: y, w: 20, h: h } };
const allEnabled = allItems.every(item => item.enabled);
const allDisabled = allItems.every(item => !item.enabled);
if (allEnabled) {
self.data.toggleAllOn = true;
} else if (allDisabled) {
self.data.toggleAllOn = false;
}
};
// Синхронизация с внешними изменениями (через интерфейс ComfyUI)
self._rs_syncFromExternal = function() {
const now = Date.now();
// Ограничиваем частоту синхронизации (не чаще 1 раза в 300 мс)
if (now - self._lastSyncTimestamp < 300) return;
self._lastSyncTimestamp = now;
@@ -182,68 +207,43 @@ app.registerExtension({
const groups = app.graph._groups || [];
let changed = false;
// Синхронизация групп
self.data.bypassedGroups.forEach(item => {
const group = groups.find(g => g.id === item.id);
if (!group) return;
const groupNodes = nodes.filter(n => isNodeInGroup(n, group));
const groupNodes = nodes.filter(n => n.comfyClass !== "RS_Bypass" && isNodeInGroup(n, group));
if (groupNodes.length === 0) return;
const allBypassed = groupNodes.every(n => n.mode === 4);
const anyBypassed = groupNodes.some(n => n.mode === 4);
// Если все забайпашены -> enabled = true; если ни одна -> false; иначе оставляем как есть (частичный байпас)
if (allBypassed && !item.enabled) {
item.enabled = true;
changed = true;
} else if (!anyBypassed && item.enabled) {
} else if (!allBypassed && item.enabled) {
item.enabled = false;
changed = true;
}
// Частичный случай: оставляем текущее enabled (может быть true или false)
// Но если включен частичный, мы не можем точно определить, поэтому лучше не трогать.
// Можно также установить enabled = anyBypassed, но тогда при частичном байпасе тоггл будет включён.
// Реализуем как anyBypassed для согласованности:
if (anyBypassed && !allBypassed) {
// Частичный байпас: если ранее было false, то меняем на true, чтобы отображать активность
if (!item.enabled) {
item.enabled = true;
changed = true;
}
}
});
// Синхронизация отдельных нод
self.data.bypassedNodes.forEach(item => {
const node = nodes.find(n => n.id === item.id);
if (!node) return;
// Проверяем, не входит ли нода в группу из кэша
const inCachedGroup = self.data.bypassedGroups.some(gItem => {
const coveredByGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
return group && isNodeInGroup(node, group);
if (!group || !isNodeInGroup(node, group)) return false;
const groupNodes = nodes.filter(nn => nn.comfyClass !== "RS_Bypass" && isNodeInGroup(nn, group));
return groupNodes.length > 0 && groupNodes.every(nn => nn.mode === 4);
});
if (inCachedGroup) {
// Если нода в группе, то она управляется группой, поэтому синхронизируем её enabled с группой
const groupEntry = self.data.bypassedGroups.find(gItem => {
const group = groups.find(g => g.id === gItem.id);
return group && isNodeInGroup(node, group);
});
if (groupEntry && groupEntry.enabled !== item.enabled) {
item.enabled = groupEntry.enabled;
changed = true;
}
} else {
// Отдельная нода
const isBypassed = node.mode === 4;
if (isBypassed !== item.enabled) {
item.enabled = isBypassed;
changed = true;
}
if (coveredByGroup) return;
const isBypassed = node.mode === 4;
if (isBypassed !== item.enabled) {
item.enabled = isBypassed;
changed = true;
}
});
// Также проверяем, есть ли новые забайпашенные ноды/группы, которых нет в кэше
// (это может быть, если пользователь забайпасил что-то вручную)
groups.forEach(group => {
if (!group || !group.bounding && !group._bounding) return;
if (!group || (!group.bounding && !group._bounding)) return;
const groupNodes = nodes.filter(n => n.comfyClass !== "RS_Bypass" && isNodeInGroup(n, group));
if (groupNodes.length === 0) return;
const allBypassed = groupNodes.every(n => n.mode === 4);
@@ -257,19 +257,47 @@ app.registerExtension({
nodes.forEach(n => {
if (n.comfyClass === "RS_Bypass") return;
if (n.mode === 4) {
const inGroup = groups.some(g => g && (g.bounding || g._bounding) && isNodeInGroup(n, g));
if (!inGroup) {
if (!self.data.bypassedNodes.some(item => item.id === n.id)) {
self.data.bypassedNodes.push({ id: n.id, enabled: true });
changed = true;
}
if (n.mode !== 4) return;
const managedByBypassedGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
if (!group || !isNodeInGroup(n, group)) return false;
const groupNodes = nodes.filter(nn => nn.comfyClass !== "RS_Bypass" && isNodeInGroup(nn, group));
return groupNodes.length > 0 && groupNodes.every(nn => nn.mode === 4);
});
if (managedByBypassedGroup) return;
if (!self.data.bypassedNodes.some(item => item.id === n.id)) {
self.data.bypassedNodes.push({ id: n.id, enabled: true });
changed = true;
} else {
const entry = self.data.bypassedNodes.find(item => item.id === n.id);
if (entry && !entry.enabled) {
entry.enabled = true;
changed = true;
}
}
});
// Если были изменения, обновляем UI и сохраняем
const beforeGroups = self.data.bypassedGroups.length;
const beforeNodes = self.data.bypassedNodes.length;
self.data.bypassedNodes = self.data.bypassedNodes.filter(item =>
nodes.some(n => n.id === item.id)
);
self.data.bypassedGroups = self.data.bypassedGroups.filter(item =>
groups.some(g => g.id === item.id)
);
if (self.data.bypassedNodes.length !== beforeNodes ||
self.data.bypassedGroups.length !== beforeGroups) {
changed = true;
}
if (changed) {
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
self.graph?.setDirtyCanvas(true, true);
@@ -277,8 +305,8 @@ app.registerExtension({
};
self.onDrawForeground = function(ctx, visibleRect) {
// Синхронизация с внешними изменениями перед отрисовкой
self._rs_syncFromExternal();
self._rs_syncToggleAllState();
self.clickZones = [];
const pad = self.padding;
@@ -291,13 +319,11 @@ app.registerExtension({
self.clickZones.push({ type: "select", x: pad + 50, y: y, w: self.size[0] - pad*2 - 50, h: rowH });
y += rowH + 10;
// Строим список из кэша, используя сохранённое состояние enabled
const nodes = app.graph._nodes || [];
const groups = app.graph._groups || [];
const displayItems = [];
// Группы из кэша
self.data.bypassedGroups.forEach(item => {
const group = groups.find(g => g.id === item.id);
if (group) {
@@ -310,27 +336,26 @@ app.registerExtension({
}
});
// Отдельные ноды из кэша, исключая те, что входят в группы из кэша (чтобы не дублировать)
self.data.bypassedNodes.forEach(item => {
const targetNode = nodes.find(n => n.id === item.id);
if (targetNode) {
// Проверяем, не входит ли нода в какую-либо группу из кэша
const inCachedGroup = self.data.bypassedGroups.some(gItem => {
const group = groups.find(g => g.id === gItem.id);
return group && isNodeInGroup(targetNode, group);
if (!targetNode) return;
const coveredByEnabledGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
return group && isNodeInGroup(targetNode, group);
});
if (!coveredByEnabledGroup) {
displayItems.push({
type: "node",
id: targetNode.id,
title: "️ " + (targetNode.title || targetNode.type),
isBypassed: item.enabled
});
if (!inCachedGroup) {
displayItems.push({
type: "node",
id: targetNode.id,
title: "️ " + (targetNode.title || targetNode.type),
isBypassed: item.enabled
});
}
}
});
// TOGGLE ALL строка
if (displayItems.length > 0) {
self.drawLabel(ctx, "TOGGLE ALL", pad, y, 100, rowH);
const toggleZone = self.drawToggle(ctx, self.data.toggleAllOn, pad + 100, y, self.size[0] - pad*2 - 100, rowH);
@@ -344,7 +369,6 @@ app.registerExtension({
y += rowH + 10;
}
// Рисуем элементы списка
displayItems.forEach((item, index) => {
const itemY = y + (index * rowH);
const zones = self.drawBypassedItem(ctx, item.title, pad, itemY, self.size[0] - pad*2, rowH, index, item.isBypassed);
@@ -382,84 +406,81 @@ app.registerExtension({
self._rs_closeMenu();
return;
}
// Синхронизация перед открытием меню
self._rs_syncFromExternal();
const existingMenu = document.getElementById("rs-bypass-menu");
if (existingMenu) existingMenu.remove();
const menu = document.createElement("div");
menu.id = "rs-bypass-menu";
menu.style.cssText = "position:fixed;background:#1a1a1a;border:2px solid #ff9800;border-radius:6px;max-height:500px;overflow-y:auto;z-index:10001;box-shadow:0 4px 20px rgba(255,152,0,0.3);min-width:350px;transition:box-shadow 0.2s;";
const searchInput = document.createElement("input");
searchInput.type = "text";
searchInput.placeholder = " Search nodes/groups...";
searchInput.style.cssText = "width:100%;padding:10px;background:#252525;color:#fff;border:none;border-bottom:1px solid #333;box-sizing:border-box;font-size:12px;outline:none;";
searchInput.value = self.data.menuSearch || "";
menu.appendChild(searchInput);
const contentDiv = document.createElement("div");
contentDiv.id = "rs-bypass-content";
menu.appendChild(contentDiv);
if (clickEvent) {
menu.style.left = (clickEvent.clientX + 8) + "px";
menu.style.top = clickEvent.clientY + "px";
}
let closeTimer = null;
const closeDelay = 300;
menu.addEventListener("mouseleave", () => {
closeTimer = setTimeout(() => {
self._rs_closeMenu();
}, closeDelay);
});
menu.addEventListener("mouseenter", () => {
if (closeTimer) {
clearTimeout(closeTimer);
closeTimer = null;
const outsideHandler = (ev) => {
const path = typeof ev.composedPath === "function" ? ev.composedPath() : null;
if (path && path.length) {
if (path.includes(menu)) return;
} else {
if (menu.contains(ev.target)) return;
}
});
self._rs_closeMenu();
};
self._rs_outsideHandler = outsideHandler;
const escHandler = (ev) => {
if (ev.key === "Escape") self._rs_closeMenu();
};
self._rs_escHandler = escHandler;
function renderContent() {
contentDiv.innerHTML = "";
const query = searchInput.value.toLowerCase();
self.data.menuSearch = query;
const groups = app.graph._groups || [];
const nodes = app.graph._nodes || [];
const filteredNodes = nodes.filter(n => n.comfyClass !== "RS_Bypass");
let hasItems = false;
groups.forEach(group => {
if (!group || !group.bounding && !group._bounding) {
return;
}
const groupNodes = filteredNodes.filter(n => isNodeInGroup(n, group));
if (groupNodes.length === 0) return;
const title = group.title || "Group " + group.id;
if (query && !title.toLowerCase().includes(query)) return;
// Проверяем, есть ли уже группа в кэше
const cachedGroup = self.data.bypassedGroups.find(item => item.id === group.id);
const isAllBypassed = cachedGroup ? cachedGroup.enabled : false;
const isPartialBypassed = false; // упростим
const isExpanded = self.data.expandedGroups[group.id] || false;
let groupColor = "#ddd";
if (isAllBypassed) groupColor = "#ff4444";
const groupItem = document.createElement("div");
groupItem.style.cssText = "padding:10px 12px;cursor:pointer;color:" + groupColor + ";border-bottom:1px solid #333;font-size:12px;display:flex;align-items:center;transition:background-color 0.15s;";
const arrow = document.createElement("span");
arrow.textContent = isExpanded ? "▼ " : "▶ ";
arrow.style.cssText = "margin-right:8px;font-size:10px;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border:1px solid #555;border-radius:4px;";
@@ -469,45 +490,47 @@ app.registerExtension({
renderContent();
};
groupItem.appendChild(arrow);
const groupText = document.createElement("span");
groupText.textContent = " " + title;
groupText.style.cssText = "flex:1;margin-left:4px;";
groupText.onclick = (ev) => {
ev.stopPropagation();
// Добавляем или удаляем группу из кэша
let entry = self.data.bypassedGroups.find(item => item.id === group.id);
if (entry) {
// Если уже есть, переключаем enabled
entry.enabled = !entry.enabled;
} else {
// Добавляем с enabled: true
entry = { id: group.id, enabled: true };
self.data.bypassedGroups.push(entry);
}
// Применяем байпас ко всем нодам группы
groupNodes.forEach(n => setNodeBypass(n, entry.enabled));
if (entry.enabled) {
self.data.bypassedNodes = self.data.bypassedNodes.filter(
nItem => !groupNodes.some(n => n.id === nItem.id)
);
}
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
renderContent();
};
groupItem.appendChild(groupText);
groupItem.onmouseover = () => groupItem.style.background = "#333";
groupItem.onmouseout = () => groupItem.style.background = "#1a1a1a";
contentDiv.appendChild(groupItem);
hasItems = true;
if (isExpanded) {
groupNodes.forEach(n => {
const nodeTitle = n.title || n.type;
if (query && !nodeTitle.toLowerCase().includes(query)) return;
const cachedNode = self.data.bypassedNodes.find(item => item.id === n.id);
const isNodeBypassed = cachedNode ? cachedNode.enabled : false;
const nodeColor = isNodeBypassed ? "#ff4444" : "#ddd";
const nodeItem = document.createElement("div");
nodeItem.textContent = "️ " + nodeTitle;
nodeItem.style.cssText = "padding:10px 12px 10px 32px;cursor:pointer;color:" + nodeColor + ";border-bottom:1px solid #333;font-size:12px;transition:background-color 0.15s;";
@@ -523,6 +546,7 @@ app.registerExtension({
self.data.bypassedNodes.push(entry);
}
setNodeBypass(n, entry.enabled);
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
renderContent();
@@ -531,16 +555,16 @@ app.registerExtension({
});
}
});
const ungroupedNodes = filteredNodes.filter(n => !groups.some(g => g && (g.bounding || g._bounding) && isNodeInGroup(n, g)));
ungroupedNodes.forEach(n => {
const title = n.title || n.type;
if (query && !title.toLowerCase().includes(query)) return;
const cachedNode = self.data.bypassedNodes.find(item => item.id === n.id);
const isBypassed = cachedNode ? cachedNode.enabled : false;
const nodeColor = isBypassed ? "#ff4444" : "#ddd";
const item = document.createElement("div");
item.textContent = "⚙️ " + title;
item.style.cssText = "padding:10px 12px;cursor:pointer;color:" + nodeColor + ";border-bottom:1px solid #333;font-size:12px;transition:background-color 0.15s;";
@@ -556,6 +580,7 @@ app.registerExtension({
self.data.bypassedNodes.push(entry);
}
setNodeBypass(n, entry.enabled);
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
renderContent();
@@ -563,7 +588,7 @@ app.registerExtension({
contentDiv.appendChild(item);
hasItems = true;
});
if (!hasItems) {
const emptyMsg = document.createElement("div");
emptyMsg.textContent = "No nodes/groups found";
@@ -571,22 +596,20 @@ app.registerExtension({
contentDiv.appendChild(emptyMsg);
}
}
searchInput.addEventListener("input", renderContent);
const closeEsc = (ev) => {
if (ev.key === "Escape") self._rs_closeMenu();
};
document.addEventListener("keydown", closeEsc);
renderContent();
document.body.appendChild(menu);
self.data.menuOpen = true;
self._rs_updateUI();
setTimeout(() => searchInput.focus(), 10);
setTimeout(() => {
document.addEventListener("pointerdown", outsideHandler, true);
document.addEventListener("keydown", escHandler);
searchInput.focus();
}, 10);
};
self._rs_closeMenu = function() {
@@ -594,6 +617,14 @@ app.registerExtension({
if (menu) {
menu.remove();
}
if (self._rs_escHandler) {
document.removeEventListener("keydown", self._rs_escHandler);
self._rs_escHandler = null;
}
if (self._rs_outsideHandler) {
document.removeEventListener("pointerdown", self._rs_outsideHandler, true);
self._rs_outsideHandler = null;
}
self.data.menuOpen = false;
self._rs_updateUI();
};
@@ -615,11 +646,9 @@ app.registerExtension({
self.data.toggleAllOn = !self.data.toggleAllOn;
const newState = self.data.toggleAllOn;
// Меняем enabled у всех элементов в кэше
self.data.bypassedGroups.forEach(item => item.enabled = newState);
self.data.bypassedNodes.forEach(item => item.enabled = newState);
// Применяем байпас
const nodes = app.graph._nodes || [];
const groups = app.graph._groups || [];
self.data.bypassedGroups.forEach(item => {
@@ -632,8 +661,8 @@ app.registerExtension({
self.data.bypassedNodes.forEach(item => {
const targetNode = nodes.find(n => n.id === item.id);
if (targetNode) {
// Проверяем, не входит ли нода в группу из кэша
const inGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
return group && isNodeInGroup(targetNode, group);
});
@@ -671,6 +700,7 @@ app.registerExtension({
setNodeBypass(targetNode, entry.enabled);
}
}
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
return true;
@@ -691,6 +721,7 @@ app.registerExtension({
}
self.data.bypassedNodes = self.data.bypassedNodes.filter(item => item.id !== zone.id);
}
self._rs_syncToggleAllState();
self._rs_syncData();
self._rs_updateUI();
return true;
@@ -732,7 +763,6 @@ app.registerExtension({
const nodes = app.graph._nodes || [];
const groups = app.graph._groups || [];
// Включаем байпас только для элементов с enabled === true
self.data.bypassedGroups.forEach(item => {
if (!item.enabled) return;
const group = groups.find(g => g.id === item.id);
@@ -746,7 +776,6 @@ app.registerExtension({
if (!item.enabled) return;
const targetNode = nodes.find(n => n.id === item.id);
if (targetNode) {
// Проверяем, не входит ли нода в уже забайпашенную группу
const inBypassedGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
@@ -763,35 +792,38 @@ app.registerExtension({
const nodes = app.graph._nodes || [];
const groups = app.graph._groups || [];
// 1. Полностью забайпашенные группы
groups.forEach(group => {
if (!group || !group.bounding && !group._bounding) return;
if (!group || (!group.bounding && !group._bounding)) return;
const groupNodes = nodes.filter(n => n.comfyClass !== "RS_Bypass" && isNodeInGroup(n, group));
if (groupNodes.length > 0 && groupNodes.every(n => n.mode === 4)) {
// Добавляем группу в кэш, если её там нет
if (!self.data.bypassedGroups.some(item => item.id === group.id)) {
self.data.bypassedGroups.push({ id: group.id, enabled: true });
} else {
// Обновляем enabled
const entry = self.data.bypassedGroups.find(item => item.id === group.id);
if (entry) entry.enabled = true;
}
}
});
// 2. Отдельные ноды с mode=4, не входящие ни в какую группу
nodes.forEach(n => {
if (n.comfyClass === "RS_Bypass") return;
if (n.mode === 4) {
const inAnyGroup = groups.some(g => g && (g.bounding || g._bounding) && isNodeInGroup(n, g));
if (!inAnyGroup) {
if (!self.data.bypassedNodes.some(item => item.id === n.id)) {
self.data.bypassedNodes.push({ id: n.id, enabled: true });
} else {
const entry = self.data.bypassedNodes.find(item => item.id === n.id);
if (entry) entry.enabled = true;
}
}
if (n.mode !== 4) return;
const managedByBypassedGroup = self.data.bypassedGroups.some(gItem => {
if (!gItem.enabled) return false;
const group = groups.find(g => g.id === gItem.id);
if (!group || !isNodeInGroup(n, group)) return false;
const groupNodes = nodes.filter(nn => nn.comfyClass !== "RS_Bypass" && isNodeInGroup(nn, group));
return groupNodes.length > 0 && groupNodes.every(nn => nn.mode === 4);
});
if (managedByBypassedGroup) return;
if (!self.data.bypassedNodes.some(item => item.id === n.id)) {
self.data.bypassedNodes.push({ id: n.id, enabled: true });
} else {
const entry = self.data.bypassedNodes.find(item => item.id === n.id);
if (entry) entry.enabled = true;
}
});
};
@@ -827,7 +859,6 @@ app.registerExtension({
try {
const restoredData = JSON.parse(stateWidget.value);
if (restoredData) {
// Преобразование при необходимости
if (Array.isArray(restoredData.nodes)) {
if (restoredData.nodes.length && typeof restoredData.nodes[0] === 'number') {
self.data.bypassedNodes = restoredData.nodes.map(id => ({ id, enabled: true }));
@@ -849,6 +880,7 @@ app.registerExtension({
}
}
self._rs_syncToggleAllState();
self._rs_applyBypass();
self._rs_updateUI();
@@ -865,6 +897,7 @@ app.registerExtension({
} else {
self._rs_applyBypass();
}
self._rs_syncToggleAllState();
self._rs_updateUI();
}, 100);