From 601e84d159e9b2b85e6e32a6366d2f3877b17744 Mon Sep 17 00:00:00 2001 From: Grin Date: Wed, 1 Jul 2026 17:23:51 -0300 Subject: [PATCH] feat(ALabel): allow custom percentage thresholds in format-icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, format-icons with N icons would divide the 0-100 range into N equal parts. This made it impossible to define custom ranges like 0%, 1-69%, 70-100%. This adds support for an alternative object syntax in format-icons: "format-icons": [ { "icon": "▁", "max": 0}, { "icon": "▅", "max": 69 }, { "icon": "▇", "max": 100 } ] The array is iterated in order and the first icon whose max value is >= the current percentage is returned. If no threshold matches, the last icon is used as fallback. The existing string array syntax remains fully supported and unchanged. Applies to both getIcon overloads, affecting all modules that use format-icons (battery, pulseaudio, network, backlight, etc.). Closes #5150 --- src/ALabel.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/ALabel.cpp b/src/ALabel.cpp index 795f87f1..46eeac2f 100644 --- a/src/ALabel.cpp +++ b/src/ALabel.cpp @@ -150,7 +150,26 @@ std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_ } if (format_icons.isArray()) { auto size = format_icons.size(); - if (size != 0U) { + if (size != 0U && format_icons[0].isObject()) { + std::string last_icon; + for (const auto& threshold : format_icons) { + if (!threshold.isObject() || !threshold["icon"].isString() || !threshold["max"].isUInt()) { + static bool warned = false; + if (!warned) { + spdlog::warn("format-icons: skipping invalid threshold object, expected {\"icon\": \"...\", \"max\": N}"); + warned = true; + } + continue; + } + last_icon = threshold["icon"].asString(); + if (percentage <= threshold["max"].asUInt()) { + return last_icon; + } + } + if (!last_icon.empty()) { + return last_icon; + } + } else if (size != 0U) { auto divisor = std::max(1U, (max == 0 ? 100U : static_cast(max)) / size); auto idx = std::clamp(percentage / divisor, 0U, size - 1); format_icons = format_icons[idx]; @@ -177,7 +196,26 @@ std::string ALabel::getIcon(uint16_t percentage, const std::vector& } if (format_icons.isArray()) { auto size = format_icons.size(); - if (size != 0U) { + if (size != 0U && format_icons[0].isObject()) { + std::string last_icon; + for (const auto& threshold : format_icons) { + if (!threshold.isObject() || !threshold["icon"].isString() || !threshold["max"].isUInt()) { + static bool warned = false; + if (!warned) { + spdlog::warn("format-icons: skipping invalid threshold object, expected {\"icon\": \"...\", \"max\": N}"); + warned = true; + } + continue; + } + last_icon = threshold["icon"].asString(); + if (percentage <= threshold["max"].asUInt()) { + return last_icon; + } + } + if (!last_icon.empty()) { + return last_icon; + } + } else if (size != 0U) { auto divisor = std::max(1U, (max == 0 ? 100U : static_cast(max)) / size); auto idx = std::clamp(percentage / divisor, 0U, size - 1); format_icons = format_icons[idx];