feat(market): fix portfolio Add button clipping; add accordion summaries

- Add button can no longer be cut off: it's now a normal widget below the group
  list (in a group with the scroll child) instead of nested inside the list child.
- Stop the modal's 28x20 WindowPadding from cascading into the nested master/detail/
  list children (pop it right after the card child begins) — that double-padding
  was squeezing the master column and the Add button.
- Right pane navigability: collapsed accordion sections now show a compact summary
  on the right (Appearance -> icon, Price -> basis, Addresses -> N selected), so a
  group's state is readable without expanding. Section titles are consistent
  title-case ("Appearance"/"Price"/"Addresses").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 19:13:35 -05:00
parent 3305be6318
commit 1fdb6656aa
2 changed files with 31 additions and 16 deletions

View File

@@ -427,6 +427,7 @@ static void RenderPortfolioEditor(App* app)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(28.0f, 20.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0));
ImGui::BeginChild("##pfCard", ImVec2(cardW, cardH), ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar);
ImGui::PopStyleVar(); // pop WindowPadding — the 28x20 applies to ##pfCard only, not nested children
material::DrawDialogTitleBar(TR("portfolio_manage_title"), &s_portfolio_editor_open);
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) s_portfolio_editor_open = false;
@@ -443,13 +444,12 @@ static void RenderPortfolioEditor(App* app)
float masterW = std::min(std::max(contentW * 0.28f, 240.0f * dp), 320.0f * dp);
float detailW = contentW - masterW - gap;
// ================= MASTER: group list =================
ImGui::BeginChild("##pfMaster", ImVec2(masterW, bodyH), false, ImGuiWindowFlags_NoScrollbar);
// ================= MASTER: scrollable group list + a pinned Add button below it =================
float addH = 34.0f * dp;
ImGui::BeginGroup();
{
const auto& entries = settings->getPortfolioEntries();
float addH = 30.0f * dp;
ImGui::BeginChild("##pfMasterList",
ImVec2(0, std::max(48.0f, ImGui::GetContentRegionAvail().y - addH - Layout::spacingXs())), false);
ImGui::BeginChild("##pfMasterList", ImVec2(masterW, std::max(48.0f, bodyH - addH - Layout::spacingSm())), false);
{
ImDrawList* mdl = ImGui::GetWindowDrawList();
if (entries.empty())
@@ -489,10 +489,11 @@ static void RenderPortfolioEditor(App* app)
if (clickedSel != -999) { commitIfNeeded(); PortfolioBeginEdit(app, clickedSel); }
}
ImGui::EndChild();
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
if (ImGui::Button(TR("portfolio_add_entry"), ImVec2(-1, addH))) { commitIfNeeded(); PortfolioBeginEdit(app, -2); }
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
// Add button lives outside the scroll child (a normal widget) so it can never be clipped.
if (ImGui::Button(TR("portfolio_add_entry"), ImVec2(masterW, addH))) { commitIfNeeded(); PortfolioBeginEdit(app, -2); }
}
ImGui::EndChild();
ImGui::EndGroup();
ImGui::SameLine(0, gap);
@@ -574,16 +575,30 @@ static void RenderPortfolioEditor(App* app)
ImGui::InputTextWithHint("##pfLabel", TR("portfolio_group_name"), s_pf_label, sizeof(s_pf_label));
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
// Accordion: exactly one section expanded at a time.
auto section = [&](const char* label, bool& openFlag) -> bool {
// Accordion: exactly one section expanded at a time. Collapsed sections show a compact
// summary on the right so a group's state is readable at a glance without expanding.
auto section = [&](const char* label, bool& openFlag, const std::string& summary) -> bool {
ImGui::SetNextItemOpen(openFlag, ImGuiCond_Always);
bool now = ImGui::CollapsingHeader(label);
if (!now && !summary.empty()) {
ImVec2 hmn = ImGui::GetItemRectMin(), hmx = ImGui::GetItemRectMax();
float sw2 = capF->CalcTextSizeA(capF->LegacySize, FLT_MAX, 0, summary.c_str()).x;
ImGui::GetWindowDrawList()->AddText(capF, capF->LegacySize,
ImVec2(hmx.x - sw2 - Layout::spacingMd(), (hmn.y + hmx.y) * 0.5f - capF->LegacySize * 0.5f),
OnSurfaceMedium(), summary.c_str());
}
if (now != openFlag) { s_pf_sec_appearance = s_pf_sec_price = s_pf_sec_addresses = false; openFlag = now; }
return openFlag;
};
// Collapsed-section summaries.
const char* basisNames[4] = { TR("portfolio_price_usd"), TR("portfolio_price_btc"),
TR("portfolio_price_drgx"), TR("portfolio_price_manual") };
std::string apSummary = s_pf_icon.empty() ? std::string(TR("portfolio_no_icon")) : s_pf_icon;
std::string prSummary = basisNames[std::max(0, std::min(3, s_pf_price_basis))];
char adSummary[48]; snprintf(adSummary, sizeof(adSummary), TR("portfolio_addresses_sel"), (int)s_pf_addrs.size());
// ---- APPEARANCE (color + outline opacity + icon) ----
if (section(TR("portfolio_appearance"), s_pf_sec_appearance)) {
if (section(TR("portfolio_appearance"), s_pf_sec_appearance, apSummary)) {
ImGui::Indent(Layout::spacingSm());
// Color picker: preset swatches + a custom-color circle that opens a picker popup.
{
@@ -698,7 +713,7 @@ static void RenderPortfolioEditor(App* app)
}
// ---- PRICE (basis, manual price, shown fields, sparkline) ----
if (section(TR("portfolio_price"), s_pf_sec_price)) {
if (section(TR("portfolio_price"), s_pf_sec_price, prSummary)) {
ImGui::Indent(Layout::spacingSm());
const char* basisItems[4] = { TR("portfolio_price_usd"), TR("portfolio_price_btc"),
TR("portfolio_price_drgx"), TR("portfolio_price_manual") };
@@ -737,7 +752,7 @@ static void RenderPortfolioEditor(App* app)
}
// ---- ADDRESSES (search, filter, select) ----
if (section(TR("portfolio_addresses_hdr"), s_pf_sec_addresses)) {
if (section(TR("portfolio_addresses_hdr"), s_pf_sec_addresses, adSummary)) {
ImGui::Indent(Layout::spacingSm());
{
char selc[48];
@@ -884,7 +899,7 @@ static void RenderPortfolioEditor(App* app)
ImGui::EndChild(); // ##pfCard
ImGui::PopStyleColor();
ImGui::PopStyleVar(2);
ImGui::PopStyleVar(); // ChildRounding (WindowPadding was popped right after BeginChild)
// Outside-click dismiss (guarded against the appearing frame and open popups).
if (!popupOpen && !ImGui::IsWindowAppearing() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)

View File

@@ -1144,8 +1144,8 @@ void I18n::loadBuiltinEnglish()
strings_["portfolio_spark_day"] = "Day";
strings_["portfolio_spark_week"] = "Week";
strings_["portfolio_spark_month"] = "Month";
strings_["portfolio_appearance"] = "APPEARANCE";
strings_["portfolio_addresses_hdr"] = "ADDRESSES";
strings_["portfolio_appearance"] = "Appearance";
strings_["portfolio_addresses_hdr"] = "Addresses";
strings_["portfolio_search"] = "Search addresses\xE2\x80\xA6";
strings_["portfolio_funded"] = "Funded";
strings_["portfolio_select_all"] = "All";