From 8501abf2efa83a3ce025b41ea9f48e3680108383 Mon Sep 17 00:00:00 2001 From: Oleg Samarin Date: Fri, 22 May 2026 09:10:00 +0300 Subject: [PATCH] Fixed profile combo not refreshing when profiles are added or removed after session start Added a PopupMenuListener to profileCombo in ClaudeSessionSelectorPanel that calls populateProfileCombo() each time the dropdown opens, preserving the current selection. This ensures the list always reflects the current state of ClaudeProfileStore. Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 1 + pom.xml | 2 +- .../ui/ClaudeSessionSelectorPanel.java | 9 ++++ .../ui/ClaudeSessionSelectorPanelTest.java | 50 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8647ae..0dffe6a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +- Fixed profile combo not refreshing when profiles are added or removed after session start - Added ability to manually add, rename, and sort models in the Model Aliases dialog - Fixed missing Claude Code icon in Tools → Options dialog diff --git a/pom.xml b/pom.xml index 602c5df6..23c24755 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.nbplugins netbeans-plugin-claude-code-gui - 1.1.3-SNAPSHOT + 1.1.4-SNAPSHOT nbm Netbeans Plugin Claude Code GUI NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE. diff --git a/src/main/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanel.java b/src/main/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanel.java index 641d1490..f77bdf54 100644 --- a/src/main/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanel.java +++ b/src/main/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanel.java @@ -179,6 +179,15 @@ public ClaudeSessionSelectorPanel(File initialDirectory, OpenListener openListen // Pre-fill from selected profile; update when profile changes profileCombo.addActionListener(e -> onProfileSelected()); + profileCombo.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { + @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent e) { + String current = (String) profileCombo.getSelectedItem(); + populateProfileCombo(); + if (current != null) profileCombo.setSelectedItem(current); + } + @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent e) {} + @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent e) {} + }); onProfileSelected(); // --- open button --- diff --git a/src/test/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanelTest.java b/src/test/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanelTest.java index 495c772b..2605f352 100644 --- a/src/test/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanelTest.java +++ b/src/test/java/io/github/nbplugins/claudecodegui/ui/ClaudeSessionSelectorPanelTest.java @@ -189,6 +189,44 @@ void projectComboSortIsStableForEqualCaseNames() { "Second group must be 'beta' variants"); } + // ------------------------------------------------------------------------- + // Profile combo refresh on popup open + // ------------------------------------------------------------------------- + + @Test + void profileComboRefreshesOnPopupOpen() { + ClaudeSessionSelectorPanel p = panel(); + javax.swing.JComboBox combo = getProfileCombo(p); + int countBefore = combo.getItemCount(); + assertTrue(countBefore >= 1, "Profile combo must have at least the Default profile"); + + // Fire the popup-will-become-visible event (simulates user opening the dropdown) + for (javax.swing.event.PopupMenuListener l : combo.getPopupMenuListeners()) { + l.popupMenuWillBecomeVisible(new javax.swing.event.PopupMenuEvent(combo)); + } + + assertEquals(countBefore, combo.getItemCount(), + "Profile combo item count must stay the same after refresh when profiles did not change"); + } + + @Test + void profileComboPreservesSelectionAfterRefresh() { + ClaudeSessionSelectorPanel p = panel(); + javax.swing.JComboBox combo = getProfileCombo(p); + + // Select the first profile (Default) + combo.setSelectedIndex(0); + String selectedBefore = (String) combo.getSelectedItem(); + + // Fire the popup listener + for (javax.swing.event.PopupMenuListener l : combo.getPopupMenuListeners()) { + l.popupMenuWillBecomeVisible(new javax.swing.event.PopupMenuEvent(combo)); + } + + assertEquals(selectedBefore, combo.getSelectedItem(), + "Profile selection must be preserved after refresh when the profile still exists"); + } + // ------------------------------------------------------------------------- // History persistence helpers // ------------------------------------------------------------------------- @@ -244,6 +282,18 @@ private static int getProfileComboIndex(ClaudeSessionSelectorPanel panel) { return nonEditable.size() > 1 ? nonEditable.get(1).getSelectedIndex() : -1; } + /** Returns the profile JComboBox (second non-editable combo). */ + private static javax.swing.JComboBox getProfileCombo(ClaudeSessionSelectorPanel panel) { + java.util.List> nonEditable = new java.util.ArrayList<>(); + for (java.awt.Component c : getAllComponents(panel)) { + if (c instanceof javax.swing.JComboBox combo && !combo.isEditable()) { + nonEditable.add(combo); + } + } + assertTrue(nonEditable.size() > 1, "Expected at least 2 non-editable combos (project + profile)"); + return nonEditable.get(1); + } + /** Recursively collects all components from a container. */ private static java.util.List getAllComponents(java.awt.Container root) { java.util.List result = new java.util.ArrayList<>();