diff --git a/src/ui/pages/settings_page.cpp b/src/ui/pages/settings_page.cpp index e152c93..74a173d 100644 --- a/src/ui/pages/settings_page.cpp +++ b/src/ui/pages/settings_page.cpp @@ -2128,49 +2128,68 @@ void RenderSettingsPage(App* app) { return std::string(buf); }; - const ImVec4 dbDim = ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()); - ImGui::Dummy(ImVec2(0, Layout::spacingLg())); Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("daemon_binary")); ImGui::Dummy(ImVec2(0, Layout::spacingXs())); - // Inline single line: Installed ( · ) · Bundled () · - ImGui::AlignTextToFramePadding(); - ImGui::TextUnformatted(TR("daemon_installed")); - ImGui::SameLine(0, Layout::spacingXs()); + // Status line: Installed ( · ) · Bundled () · . + // Built as color-tagged atoms and laid out with manual wrapping — as one long inline + // row of SameLine() Text calls it overran the content width and clipped its colored + // tail at narrow windows / higher font scale (the status was effectively hidden). + struct DbAtom { std::string text; ImU32 col; bool sep; }; + std::vector dbAtoms; + const ImU32 dbNorm = ImGui::GetColorU32(ImGuiCol_Text); + const ImU32 dbDimU = OnSurfaceMedium(); + + dbAtoms.push_back({ TR("daemon_installed"), dbNorm, false }); if (inst.exists) { - ImGui::TextUnformatted(inst.version.empty() ? TR("unknown") : inst.version.c_str()); - ImGui::SameLine(0, Layout::spacingXs()); - ImGui::TextColored(dbDim, "(%s · %s)", - util::Platform::formatFileSize(inst.size).c_str(), - fmtDate(inst.modifiedEpoch).c_str()); + dbAtoms.push_back({ inst.version.empty() ? std::string(TR("unknown")) : inst.version, dbNorm, false }); + char dbParen[96]; + std::snprintf(dbParen, sizeof(dbParen), "(%s · %s)", + util::Platform::formatFileSize(inst.size).c_str(), + fmtDate(inst.modifiedEpoch).c_str()); + dbAtoms.push_back({ dbParen, dbDimU, false }); } else { - ImGui::TextColored(dbDim, "%s", TR("daemon_not_installed")); + dbAtoms.push_back({ TR("daemon_not_installed"), dbDimU, false }); } - ImGui::SameLine(0, Layout::spacingXs()); - ImGui::TextColored(dbDim, "·"); - ImGui::SameLine(0, Layout::spacingXs()); - ImGui::AlignTextToFramePadding(); - ImGui::TextUnformatted(TR("daemon_bundled")); - ImGui::SameLine(0, Layout::spacingXs()); + dbAtoms.push_back({ "·", dbDimU, true }); + dbAtoms.push_back({ TR("daemon_bundled"), dbNorm, false }); if (bun.available) { - ImGui::TextUnformatted(bun.version.empty() ? TR("unknown") : bun.version.c_str()); - ImGui::SameLine(0, Layout::spacingXs()); - ImGui::TextColored(dbDim, "(%s)", util::Platform::formatFileSize(bun.size).c_str()); + dbAtoms.push_back({ bun.version.empty() ? std::string(TR("unknown")) : bun.version, dbNorm, false }); + dbAtoms.push_back({ "(" + util::Platform::formatFileSize(bun.size) + ")", dbDimU, false }); } else { - ImGui::TextColored(dbDim, "%s", TR("daemon_none_bundled")); + dbAtoms.push_back({ TR("daemon_none_bundled"), dbDimU, false }); } if (bun.available) { const bool sameSize = inst.exists && inst.size == bun.size; - ImGui::SameLine(0, Layout::spacingXs()); - ImGui::TextColored(dbDim, "·"); - ImGui::SameLine(0, Layout::spacingXs()); + dbAtoms.push_back({ "·", dbDimU, true }); if (!inst.exists) - ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "%s", TR("daemon_status_missing")); + dbAtoms.push_back({ TR("daemon_status_missing"), ImGui::ColorConvertFloat4ToU32(ImVec4(1.0f, 0.8f, 0.2f, 1.0f)), false }); else if (sameSize) - ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), "%s", TR("daemon_status_match")); + dbAtoms.push_back({ TR("daemon_status_match"), ImGui::ColorConvertFloat4ToU32(ImVec4(0.3f, 0.8f, 0.3f, 1.0f)), false }); else - ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "%s", TR("daemon_status_differ")); + dbAtoms.push_back({ TR("daemon_status_differ"), ImGui::ColorConvertFloat4ToU32(ImVec4(1.0f, 0.8f, 0.2f, 1.0f)), false }); + } + + // Lay the atoms out left-to-right, wrapping to a new line when the next one would + // exceed the content width. A "·" separator is dropped when it (plus the atom after + // it) doesn't fit, so a wrapped line never starts or ends with a dangling separator. + const float dbAvail = ImGui::GetContentRegionAvail().x; + const float dbGap = Layout::spacingXs(); + float dbX = 0.0f; + ImGui::AlignTextToFramePadding(); + for (std::size_t i = 0; i < dbAtoms.size(); ++i) { + const float w = ImGui::CalcTextSize(dbAtoms[i].text.c_str()).x; + if (dbAtoms[i].sep) { + const float nextW = (i + 1 < dbAtoms.size()) + ? ImGui::CalcTextSize(dbAtoms[i + 1].text.c_str()).x : 0.0f; + if (dbX > 0.0f && dbX + dbGap + w + dbGap + nextW > dbAvail) continue; + } + const bool wrap = (dbX > 0.0f) && (dbX + dbGap + w > dbAvail); + if (dbX > 0.0f && !wrap) { ImGui::SameLine(0, dbGap); dbX += dbGap; } + else if (wrap) { dbX = 0.0f; } + ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(dbAtoms[i].col), "%s", dbAtoms[i].text.c_str()); + dbX += w; } // In-app node update: download + verify the latest dragonxd from the project Gitea.