fix(balance): unique IDs + scope filter for the Add-to-portfolio menu
The address context menu's "Add to portfolio" submenu built each item with MenuItem(label), whose ImGui ID is derived from the label — so two groups with the same label (or two empty labels) collided, routing a click to the wrong group, and a blank label rendered as an invisible row. - PushID(pi) per item gives a stable unique ID regardless of label, and an empty label now shows the "new entry" placeholder. - Filter the list to the active wallet's groups (or legacy/unscoped), matching the Market summary and editor, so an address can't be added to a different wallet's group. The "no entries" placeholder now also covers the case where every group is filtered out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -680,19 +680,31 @@ void RenderSharedAddressList(App* app, float listH, float availW,
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::BeginMenu(TR("portfolio_add_to"))) {
|
if (ImGui::BeginMenu(TR("portfolio_add_to"))) {
|
||||||
const auto& pf = app->settings()->getPortfolioEntries();
|
const auto& pf = app->settings()->getPortfolioEntries();
|
||||||
if (pf.empty()) {
|
const std::string activeHash = app->activeWalletIdentityHash();
|
||||||
ImGui::MenuItem(TR("portfolio_no_entries"), nullptr, false, false);
|
int shown = 0;
|
||||||
}
|
|
||||||
for (int pi = 0; pi < (int)pf.size(); pi++) {
|
for (int pi = 0; pi < (int)pf.size(); pi++) {
|
||||||
|
// Only this wallet's groups (or legacy/unscoped), matching the Market summary —
|
||||||
|
// don't offer to add this address to another wallet's group.
|
||||||
|
if (!(pf[pi].scope.empty() || activeHash.empty() || pf[pi].scope == activeHash))
|
||||||
|
continue;
|
||||||
|
// PushID keeps the item ID unique even when two groups share a label (a
|
||||||
|
// label-derived MenuItem ID would collide); a blank label shows a placeholder
|
||||||
|
// instead of rendering as an invisible row.
|
||||||
|
ImGui::PushID(pi);
|
||||||
bool inSet = dragonx::data::PortfolioEntryContains(pf[pi].addresses, addr.address);
|
bool inSet = dragonx::data::PortfolioEntryContains(pf[pi].addresses, addr.address);
|
||||||
if (ImGui::MenuItem(pf[pi].label.c_str(), nullptr, inSet)) {
|
const char* lbl = pf[pi].label.empty() ? TR("portfolio_new_entry") : pf[pi].label.c_str();
|
||||||
|
if (ImGui::MenuItem(lbl, nullptr, inSet)) {
|
||||||
auto entries = pf; // copy, mutate, persist
|
auto entries = pf; // copy, mutate, persist
|
||||||
if (inSet) dragonx::data::PortfolioEntryRemove(entries[pi].addresses, addr.address);
|
if (inSet) dragonx::data::PortfolioEntryRemove(entries[pi].addresses, addr.address);
|
||||||
else dragonx::data::PortfolioEntryAdd(entries[pi].addresses, addr.address);
|
else dragonx::data::PortfolioEntryAdd(entries[pi].addresses, addr.address);
|
||||||
app->settings()->setPortfolioEntries(entries);
|
app->settings()->setPortfolioEntries(entries);
|
||||||
app->settings()->save();
|
app->settings()->save();
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
shown++;
|
||||||
}
|
}
|
||||||
|
if (shown == 0)
|
||||||
|
ImGui::MenuItem(TR("portfolio_no_entries"), nullptr, false, false);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
effects::ImGuiAcrylic::EndAcrylicPopup();
|
effects::ImGuiAcrylic::EndAcrylicPopup();
|
||||||
|
|||||||
Reference in New Issue
Block a user