From 286109e146c6421188a22796ad3f3f7512234347 Mon Sep 17 00:00:00 2001 From: Danielle Cox Date: Thu, 26 Mar 2026 17:52:21 -0400 Subject: [PATCH] Fix duplicate port rendering when PortType.both is used When a port has PortType.both, it returns true for both isInput and isOutput, causing it to appear in both node.inputPorts and node.outputPorts lists. This created duplicate widgets with the same key. Fixed by iterating over node.ports directly instead of concatenating inputPorts and outputPorts. Fixes: - lib/src/nodes/node_container.dart: Render ports from single list - lib/src/editor/node_flow_editor_widget_handlers.dart: Find port from single list --- .../node_flow_editor_widget_handlers.dart | 6 ++---- .../lib/src/nodes/node_container.dart | 18 +++++------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/packages/vyuh_node_flow/lib/src/editor/node_flow_editor_widget_handlers.dart b/packages/vyuh_node_flow/lib/src/editor/node_flow_editor_widget_handlers.dart index 2a36846..38f6b91 100644 --- a/packages/vyuh_node_flow/lib/src/editor/node_flow_editor_widget_handlers.dart +++ b/packages/vyuh_node_flow/lib/src/editor/node_flow_editor_widget_handlers.dart @@ -84,10 +84,8 @@ extension _WidgetGestureHandlers on _NodeFlowEditorState { if (node == null) return; // Find the port - final port = [ - ...node.inputPorts, - ...node.outputPorts, - ].where((p) => p.id == portId).firstOrNull; + // Use node.ports directly to avoid duplicates when port has PortType.both + final port = node.ports.where((p) => p.id == portId).firstOrNull; if (port == null) return; widget.controller.events.port?.onContextMenu?.call( diff --git a/packages/vyuh_node_flow/lib/src/nodes/node_container.dart b/packages/vyuh_node_flow/lib/src/nodes/node_container.dart index a7c715a..edfaac9 100644 --- a/packages/vyuh_node_flow/lib/src/nodes/node_container.dart +++ b/packages/vyuh_node_flow/lib/src/nodes/node_container.dart @@ -181,19 +181,11 @@ class NodeContainer extends StatelessWidget { ), ), - // Input ports (only when LOD allows and ports exist) - // Use port.isOutput to respect PortType (input, output, both) - // rather than list membership - if (lodVisibility.showPorts && node.inputPorts.isNotEmpty) - ...node.inputPorts.map( - (port) => _buildPort(context, port, port.isOutput), - ), - - // Output ports (only when LOD allows and ports exist) - // Use port.isOutput to respect PortType (input, output, both) - // rather than list membership - if (lodVisibility.showPorts && node.outputPorts.isNotEmpty) - ...node.outputPorts.map( + // Ports (only when LOD allows and ports exist) + // Iterate over all ports directly to avoid duplicate rendering + // when a port has PortType.both (would appear in both inputPorts and outputPorts) + if (lodVisibility.showPorts && node.ports.isNotEmpty) + ...node.ports.map( (port) => _buildPort(context, port, port.isOutput), ),