[feat] Restore group node conversion menu with deprecated label (#4967)

## Summary
- Partially reverts commit c84218d6 to restore group node functionality
in context menus
- Adds "(Deprecated)" label to indicate the feature is deprecated
- Fixes TypeError when right-clicking on group nodes
- Re-enables tests that were disabled when the feature was removed

## Changes
1. **Restored context menu options** - Added back "Convert to Group Node
(Deprecated)" and "Manage Group Nodes" menu items
2. **Fixed null reference error** - Added null-safe operator to prevent
errors when right-clicking group nodes
3. **Re-enabled tests** - Restored 7 tests that were disabled in commit
586f8824

## Test plan
- [x] Right-click on canvas → verify "Convert to Group Node
(Deprecated)" appears
- [x] Right-click on nodes → verify the same menu option appears
- [x] Select multiple nodes and use the menu option → verify conversion
works
- [x] Right-click on group nodes → verify no errors occur
- [x] Run browser tests → verify all re-enabled tests pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-4967-feat-Restore-group-node-conversion-menu-with-deprecated-label-24e6d73d36508149a6f2dbef47223e94)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Christian Byrne
2025-08-13 15:13:18 -07:00
committed by GitHub
parent db1b81b7ff
commit 4a3bd39650
10 changed files with 65 additions and 11 deletions

View File

@@ -3,6 +3,7 @@ import { type NodeId } from '@/lib/litegraph/src/LGraphNode'
import {
type ExecutableLGraphNode,
type ExecutionId,
LGraphCanvas,
LGraphNode,
LiteGraph,
SubgraphNode
@@ -1172,8 +1173,7 @@ export class GroupNodeHandler {
// @ts-expect-error fixme ts strict error
getExtraMenuOptions?.apply(this, arguments)
// @ts-expect-error fixme ts strict error
let optionIndex = options.findIndex((o) => o.content === 'Outputs')
let optionIndex = options.findIndex((o) => o?.content === 'Outputs')
if (optionIndex === -1) optionIndex = options.length
else optionIndex++
options.splice(
@@ -1634,6 +1634,57 @@ export class GroupNodeHandler {
}
}
function addConvertToGroupOptions() {
// @ts-expect-error fixme ts strict error
function addConvertOption(options, index) {
const selected = Object.values(app.canvas.selected_nodes ?? {})
const disabled =
selected.length < 2 ||
selected.find((n) => GroupNodeHandler.isGroupNode(n))
options.splice(index, null, {
content: `Convert to Group Node (Deprecated)`,
disabled,
callback: convertSelectedNodesToGroupNode
})
}
// @ts-expect-error fixme ts strict error
function addManageOption(options, index) {
const groups = app.graph.extra?.groupNodes
const disabled = !groups || !Object.keys(groups).length
options.splice(index, null, {
content: `Manage Group Nodes`,
disabled,
callback: () => manageGroupNodes()
})
}
// Add to canvas
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
// @ts-expect-error fixme ts strict error
const options = getCanvasMenuOptions.apply(this, arguments)
const index = options.findIndex((o) => o?.content === 'Add Group')
const insertAt = index === -1 ? options.length - 1 : index + 2
addConvertOption(options, insertAt)
addManageOption(options, insertAt + 1)
return options
}
// Add to nodes
const getNodeMenuOptions = LGraphCanvas.prototype.getNodeMenuOptions
LGraphCanvas.prototype.getNodeMenuOptions = function (node) {
// @ts-expect-error fixme ts strict error
const options = getNodeMenuOptions.apply(this, arguments)
if (!GroupNodeHandler.isGroupNode(node)) {
const index = options.findIndex((o) => o?.content === 'Properties')
const insertAt = index === -1 ? options.length - 1 : index
addConvertOption(options, insertAt)
}
return options
}
}
const replaceLegacySeparators = (nodes: ComfyNode[]): void => {
for (const node of nodes) {
if (typeof node.type === 'string' && node.type.startsWith('workflow/')) {
@@ -1729,6 +1780,9 @@ const ext: ComfyExtension = {
}
}
],
setup() {
addConvertToGroupOptions()
},
async beforeConfigureGraph(
graphData: ComfyWorkflowJSON,
missingNodeTypes: string[]