From 35df5a483b408272bfc0db25a3b67f85fcf776cc Mon Sep 17 00:00:00 2001 From: Turann_ Date: Tue, 20 Jan 2026 10:33:03 +0300 Subject: [PATCH] Add new icon and make use of it - Adds battery-charging-2 icon - Shows new icon if plugged in while battery is not charging. --- Commons/IconsTabler.qml | 1 + Modules/Bar/Widgets/Battery.qml | 36 +++++++++++++++---------- Modules/Panels/Battery/BatteryPanel.qml | 8 ++++-- Services/Hardware/BatteryService.qml | 5 +++- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Commons/IconsTabler.qml b/Commons/IconsTabler.qml index 4530c43d6..0c37f44eb 100644 --- a/Commons/IconsTabler.qml +++ b/Commons/IconsTabler.qml @@ -79,6 +79,7 @@ Singleton { "star-off": "star-off", "battery-exclamation": "battery-exclamation", "common.charging": "common.charging", + "battery-charging-2": "battery-charging-2", "battery-4": "battery-4", "battery-3": "battery-3", "battery-2": "battery-2", diff --git a/Modules/Bar/Widgets/Battery.qml b/Modules/Bar/Widgets/Battery.qml index 0727fdc80..ffe39fa15 100644 --- a/Modules/Bar/Widgets/Battery.qml +++ b/Modules/Bar/Widgets/Battery.qml @@ -39,7 +39,7 @@ Item { readonly property bool hideIfNotDetected: widgetSettings.hideIfNotDetected !== undefined ? widgetSettings.hideIfNotDetected : widgetMetadata.hideIfNotDetected readonly property bool hideIfIdle: widgetSettings.hideIfIdle !== undefined ? widgetSettings.hideIfIdle : widgetMetadata.hideIfIdle // Only show low battery warning if device is ready (prevents false positive during initialization) - readonly property bool isLowBattery: isReady && !charging && percent <= warningThreshold + readonly property bool isLowBattery: isReady && (!charging && !isPluggedIn) && percent <= warningThreshold // Visibility: show if hideIfNotDetected is false, or if battery is ready (after initialization) readonly property bool shouldShow: !hideIfNotDetected || (isReady && (hideIfIdle ? (charging || battery.state === UPowerDeviceState.Discharging) : true)) @@ -50,6 +50,7 @@ Item { readonly property bool testMode: false readonly property int testPercent: 35 readonly property bool testCharging: false + readonly property bool testPluggedIn: false readonly property string deviceNativePath: widgetSettings.deviceNativePath || "" @@ -127,6 +128,7 @@ Item { readonly property bool isReady: testMode ? true : (initializationComplete && battery && battery.ready && isDevicePresent && (battery.percentage !== undefined || hasBluetoothBattery)) readonly property real percent: testMode ? testPercent : (isReady ? (hasBluetoothBattery ? (bluetoothDevice.battery * 100) : (battery.percentage * 100)) : 0) readonly property bool charging: testMode ? testCharging : (isReady ? chargingStatus(battery.state) : false) // Assuming not charging if battery is not ready + readonly property bool isPluggedIn: testMode ? testPluggedIn : (isReady ? getPluggedInStatus(battery.state) : false) // We can be plugged in or charging but can't both. property bool hasNotifiedLowBattery: false implicitWidth: pill.width @@ -135,8 +137,6 @@ Item { function chargingStatus(state) { switch (state) { case UPowerDeviceState.Charging: // 1 - case UPowerDeviceState.FullyCharged: // 4 - case UPowerDeviceState.PendingCharge: // 5 return true; case UPowerDeviceState.Discharging: // 2 case UPowerDeviceState.Empty: // 3 @@ -146,15 +146,23 @@ Item { return true; // unknown state 0 Fix #1417 } } - - function maybeNotify(currentPercent, isCharging) { - if (!isCharging && !hasNotifiedLowBattery && currentPercent <= warningThreshold) { + function getPluggedInStatus(state) { + switch (state) { + case UPowerDeviceState.FullyCharged: // 4 + case UPowerDeviceState.PendingCharge: // 5 + return true; + default: + return false; + } + } + function maybeNotify(currentPercent, isCharging, isPluggedIn) { + if ((!isCharging && !isPluggedIn) && !hasNotifiedLowBattery && currentPercent <= warningThreshold) { hasNotifiedLowBattery = true; ToastService.showWarning(I18n.tr("toast.battery.low"), I18n.tr("toast.battery.low-desc", { "percent": Math.round(currentPercent) })); - // Logger.e("Battery", "Low battery at " + currentPercent + "%", "isCharging: " + isCharging); // debug - } else if (hasNotifiedLowBattery && (isCharging || currentPercent > warningThreshold + 5)) { + // Logger.e("Battery", "Low battery at " + currentPercent + "%", "isCharging: " + isCharging, "isPluggedIn: " + isPluggedIn); // debug + } else if (hasNotifiedLowBattery && (isCharging || isPluggedIn || currentPercent > warningThreshold + 5)) { hasNotifiedLowBattery = false; } } @@ -167,15 +175,15 @@ Item { target: battery function onPercentageChanged() { if (battery) { - maybeNotify(getCurrentPercent(), chargingStatus(battery.state)); + maybeNotify(getCurrentPercent(), chargingStatus(battery.state), getPluggedInStatus(battery.state)); } } function onStateChanged() { if (battery) { - if (chargingStatus(battery.state)) { + if (chargingStatus(battery.state) || getPluggedInStatus(battery.state)) { hasNotifiedLowBattery = false; } - maybeNotify(getCurrentPercent(), chargingStatus(battery.state)); + maybeNotify(getCurrentPercent(), chargingStatus(battery.state), getPluggedInStatus(battery.state)); } } } @@ -184,7 +192,7 @@ Item { target: bluetoothDevice function onBatteryChanged() { if (bluetoothDevice && hasBluetoothBattery) { - maybeNotify(bluetoothDevice.battery * 100, battery ? chargingStatus(battery.state) : false); + maybeNotify(bluetoothDevice.battery * 100, battery ? chargingStatus(battery.state) : false, battery ? getPluggedInStatus(battery.state) : false); } } } @@ -217,7 +225,7 @@ Item { screen: root.screen oppositeDirection: BarService.getPillDirection(root) - icon: testMode ? BatteryService.getIcon(testPercent, testCharging, true) : BatteryService.getIcon(percent, charging, isReady) + icon: testMode ? BatteryService.getIcon(testPercent, testCharging, testPluggedIn, true) : BatteryService.getIcon(percent, charging, isPluggedIn, isReady) text: (isReady || testMode) ? Math.round(percent) : "-" suffix: "%" autoHide: false @@ -259,7 +267,7 @@ Item { })); } else { // Rate is 0 - check if plugged in (charging state) or idle - lines.push(charging ? I18n.tr("battery.plugged-in") : I18n.tr("common.idle")); + lines.push(isPluggedIn ? I18n.tr("battery.plugged-in") : I18n.tr("common.idle")); } } else { lines.push(charging ? I18n.tr("common.charging") : I18n.tr("common.discharging")); diff --git a/Modules/Panels/Battery/BatteryPanel.qml b/Modules/Panels/Battery/BatteryPanel.qml index 3b2ca3539..798260d6e 100644 --- a/Modules/Panels/Battery/BatteryPanel.qml +++ b/Modules/Panels/Battery/BatteryPanel.qml @@ -110,6 +110,7 @@ SmartPanel { readonly property bool isReady: battery && battery.ready && isDevicePresent && (battery.percentage !== undefined || hasBluetoothBattery) readonly property int percent: isReady ? Math.round(hasBluetoothBattery ? (bluetoothDevice.battery * 100) : (battery.percentage * 100)) : -1 readonly property bool charging: isReady ? battery.state === UPowerDeviceState.Charging : false + readonly property bool isPluggedIn: isReady ? (battery.state === UPowerDeviceState.FullyCharged || battery.state === UPowerDeviceState.PendingCharge) : false readonly property bool healthAvailable: isReady && battery.healthSupported readonly property int healthPercent: healthAvailable ? Math.round(battery.healthPercentage) : -1 @@ -146,9 +147,12 @@ SmartPanel { "time": Time.formatVagueHumanReadableDuration(battery.timeToEmpty) }); } + if (!charging && isPluggedIn) { + return I18n.tr("battery.plugged-in"); // i18n: Could be Plugged in, not charging? Ask maintainers if i not forgot + } return I18n.tr("common.idle"); } - readonly property string iconName: BatteryService.getIcon(percent, charging, isReady) + readonly property string iconName: BatteryService.getIcon(percent, charging, isPluggedIn, isReady) property var batteryWidgetInstance: BarService.lookupWidget("Battery", screen ? screen.name : null) readonly property var batteryWidgetSettings: batteryWidgetInstance ? batteryWidgetInstance.widgetSettings : null @@ -215,7 +219,7 @@ SmartPanel { NIcon { pointSize: Style.fontSizeXXL - color: charging ? Color.mPrimary : Color.mOnSurface + color: (charging || isPluggedIn) ? Color.mPrimary : Color.mOnSurface icon: iconName } diff --git a/Services/Hardware/BatteryService.qml b/Services/Hardware/BatteryService.qml index 238f5378d..1eecb7f0c 100644 --- a/Services/Hardware/BatteryService.qml +++ b/Services/Hardware/BatteryService.qml @@ -80,13 +80,16 @@ Singleton { return primaryDevice.connected === true; } - function getIcon(percent, charging, isReady) { + function getIcon(percent, charging, pluggedIn, isReady) { if (!isReady) { return "battery-exclamation"; } if (charging) { return "common.charging"; } + if (pluggedIn) { + return "battery-charging-2"; + } if (percent >= 90) { return "battery-4"; }