implement proper battery warnings

This commit is contained in:
notiant
2026-02-02 20:15:47 +01:00
committed by GitHub
parent b66a8c75ca
commit 42a4682a8b
7 changed files with 104 additions and 96 deletions
+7 -6
View File
@@ -287,7 +287,6 @@
"battery": {
"battery-health": "Battery health",
"battery-level": "Battery level",
"capacity-level": "Capacity: {level}",
"charging-rate": "Charging rate: {rate} W",
"discharging-rate": "Discharging rate: {rate} W",
"health": "Health: {percent}%",
@@ -1183,8 +1182,6 @@
"history-low-urgency-label": "Save low urgency to history",
"history-normal-urgency-description": "Save normal priority notifications to history.",
"history-normal-urgency-label": "Save normal urgency to history",
"media-toast-description": "Show a toast when media playback state changes.",
"media-toast-label": "Media",
"monitors-desc": "Show notification on specific monitors. Defaults to all if none are chosen.",
"settings-always-on-top-description": "Display notifications above fullscreen windows and other layers.",
"settings-background-opacity-description": "Adjust the opacity of notification backgrounds.",
@@ -1223,8 +1220,12 @@
"sounds-volume-description": "Adjust the volume level for notification sounds.",
"sounds-volume-label": "Sound volume",
"toast-desc": "Configure toast appearance and behavior.",
"toast-battery-description": "Show a warning when the battery level falls below this percentage.",
"toast-battery-label": "Battery warning",
"toast-keyboard-description": "Show a toast when the keyboard layout changes.",
"toast-keyboard-label": "Keyboard layout"
"toast-keyboard-label": "Keyboard layout",
"toast-media-description": "Show a toast when media playback state changes.",
"toast-media-label": "Media"
},
"osd": {
"always-on-top-description": "Display OSD above fullscreen windows and other layers.",
@@ -1558,9 +1559,9 @@
},
"battery": {
"critical": "Critical battery",
"critical-desc": "Battery is at {percent}%. Please connect the charger immediately",
"critical-desc": "Battery is at {percent}%. Please connect the charger immediately.",
"low": "Low battery",
"low-desc": "Battery is at {percent}%. Please connect the charger"
"low-desc": "Battery is at {percent}%. Please connect the charger."
},
"bluetooth": {
"address-copied": "Address copied to clipboard",
+4 -4
View File
@@ -270,8 +270,6 @@
"swapCriticalThreshold": 90,
"diskWarningThreshold": 80,
"diskCriticalThreshold": 90,
"batteryWarningThreshold": 20,
"batteryCriticalThreshold": 5,
"cpuPollingInterval": 1000,
"gpuPollingInterval": 3000,
"enableDgpuMonitoring": false,
@@ -353,7 +351,6 @@
"lowUrgencyDuration": 3,
"normalUrgencyDuration": 8,
"criticalUrgencyDuration": 15,
"enableKeyboardLayoutToast": true,
"saveToHistory": {
"low": true,
"normal": true,
@@ -368,7 +365,10 @@
"lowSoundFile": "",
"excludedApps": "discord,firefox,chrome,chromium,edge"
},
"enableMediaToast": false
"enableMediaToast": false,
"enableKeyboardLayoutToast": true,
"batteryWarningThreshold": 20,
"batteryCriticalThreshold": 5
},
"osd": {
"enabled": true,
+3 -3
View File
@@ -482,8 +482,6 @@ Singleton {
property int swapCriticalThreshold: 90
property int diskWarningThreshold: 80
property int diskCriticalThreshold: 90
property int batteryWarningThreshold: 20
property int batteryCriticalThreshold: 5
property int cpuPollingInterval: 3000
property int tempPollingInterval: 3000
property int gpuPollingInterval: 3000
@@ -575,7 +573,6 @@ Singleton {
property int lowUrgencyDuration: 3
property int normalUrgencyDuration: 8
property int criticalUrgencyDuration: 15
property bool enableKeyboardLayoutToast: true
property JsonObject saveToHistory: JsonObject {
property bool low: true
property bool normal: true
@@ -591,6 +588,9 @@ Singleton {
property string excludedApps: "discord,firefox,chrome,chromium,edge"
}
property bool enableMediaToast: false
property bool enableKeyboardLayoutToast: true
property int batteryWarningThreshold: 20
property int batteryCriticalThreshold: 5
}
// on-screen display
+2 -2
View File
@@ -100,8 +100,8 @@ Item {
autoHide: false
forceOpen: isReady && displayMode === "alwaysShow"
forceClose: displayMode === "alwaysHide" || !isReady
customBackgroundColor: (isCharging || isPluggedIn) ? Color.mPrimary : ((isLowBattery || isCriticalBattery) ? Color.mError : "transparent")
customTextIconColor: (isCharging || isPluggedIn) ? Color.mOnPrimary : ((isLowBattery || isCriticalBattery) ? Color.mOnError : "transparent")
customBackgroundColor: isCharging ? Color.mPrimary : ((isLowBattery || isCriticalBattery) ? Color.mError : "transparent")
customTextIconColor: isCharging ? Color.mOnPrimary : ((isLowBattery || isCriticalBattery) ? Color.mOnError : "transparent")
tooltipText: {
let lines = [];
@@ -11,16 +11,12 @@ ColumnLayout {
NCheckbox {
Layout.fillWidth: true
label: I18n.tr("panels.notifications.media-toast-label")
description: I18n.tr("panels.notifications.media-toast-description")
label: I18n.tr("panels.notifications.toast-media-label")
description: I18n.tr("panels.notifications.toast-media-description")
checked: Settings.data.notifications.enableMediaToast
onToggled: checked => Settings.data.notifications.enableMediaToast = checked
}
NDivider {
Layout.fillWidth: true
}
NCheckbox {
Layout.fillWidth: true
label: I18n.tr("panels.notifications.toast-keyboard-label")
@@ -28,4 +24,71 @@ ColumnLayout {
checked: Settings.data.notifications.enableKeyboardLayoutToast
onToggled: checked => Settings.data.notifications.enableKeyboardLayoutToast = checked
}
NDivider {
Layout.fillWidth: true
}
RowLayout {
NLabel {
label: I18n.tr("panels.notifications.toast-battery-label")
description: I18n.tr("panels.notifications.toast-battery-description")
}
Item {
Layout.fillWidth: true
}
GridLayout {
Layout.fillWidth: true
Layout.topMargin: Style.marginM
columns: 2
columnSpacing: Style.marginM
rowSpacing: Style.marginM
NText {
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
text: I18n.tr("panels.system-monitor.threshold-warning")
pointSize: Style.fontSizeS
color: Color.mOnSurfaceVariant
}
NText {
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
text: I18n.tr("panels.system-monitor.threshold-critical")
pointSize: Style.fontSizeS
color: Color.mOnSurfaceVariant
}
NSpinBox {
Layout.alignment: Qt.AlignHCenter
from: 0
to: 100
stepSize: 5
value: Settings.data.notifications.batteryWarningThreshold
defaultValue: Settings.getDefaultValue("notifications.batteryWarningThreshold")
suffix: "%"
onValueChanged: {
Settings.data.notifications.batteryWarningThreshold = value;
if (Settings.data.notifications.batteryCriticalThreshold > value) {
Settings.data.notifications.batteryCriticalThreshold = value;
}
}
}
NSpinBox {
Layout.alignment: Qt.AlignHCenter
from: 0
to: Settings.data.notifications.batteryWarningThreshold
stepSize: 5
value: Settings.data.notifications.batteryCriticalThreshold
defaultValue: Settings.getDefaultValue("notifications.batteryCriticalThreshold")
suffix: "%"
onValueChanged: Settings.data.notifications.batteryCriticalThreshold = value
}
}
}
}
@@ -243,38 +243,5 @@ ColumnLayout {
suffix: "%"
onValueChanged: Settings.data.systemMonitor.diskCriticalThreshold = value
}
// Battery
NText {
text: I18n.tr("common.battery")
pointSize: Style.fontSizeM
}
NSpinBox {
Layout.alignment: Qt.AlignHCenter
from: 0
to: 100
stepSize: 5
value: Settings.data.systemMonitor.batteryWarningThreshold
defaultValue: Settings.getDefaultValue("systemMonitor.batteryWarningThreshold")
suffix: "%"
onValueChanged: {
Settings.data.systemMonitor.batteryWarningThreshold = value;
if (Settings.data.systemMonitor.batteryCriticalThreshold > value) {
Settings.data.systemMonitor.batteryCriticalThreshold = value;
}
}
}
NSpinBox {
Layout.alignment: Qt.AlignHCenter
from: 0
to: Settings.data.systemMonitor.batteryWarningThreshold
stepSize: 5
value: Settings.data.systemMonitor.batteryCriticalThreshold
defaultValue: Settings.getDefaultValue("systemMonitor.batteryCriticalThreshold")
suffix: "%"
onValueChanged: Settings.data.systemMonitor.batteryCriticalThreshold = value
}
}
}
+19 -42
View File
@@ -154,16 +154,10 @@ Singleton {
}
function isCriticalBattery(device) {
if (!device || !isDeviceReady(device)) {
return false;
}
return (!isCharging(device) && !isPluggedIn(device)) && getPercentage(device) <= criticalThreshold;
}
function isLowBattery(device) {
if (!device || !isDeviceReady(device)) {
return false;
}
return (!isCharging(device) && !isPluggedIn(device)) && getPercentage(device) <= warningThreshold && getPercentage(device) > criticalThreshold;
}
@@ -277,34 +271,29 @@ Singleton {
}
function checkDevice(device) {
if (!device || !isDeviceReady(device)) {
if (!device || !device.ready) {
return;
}
const percentage = getPercentage(device);
const charging = isCharging(device);
const plugged = isPluggedIn(device);
const level = "low"; //isLowBattery(device) ? "low" : isCriticalBattery(device) ? "critical" : "";
Logger.e("BatteryServiceDebug", "Device: " + device.model + " Percentage: " + percentage + " Charging: " + charging + " Plugged: " + plugged + " Level: " + level);
const pluggedIn = isPluggedIn(device);
const level = isLowBattery(device) ? "low" : (isCriticalBattery(device) ? "critical" : "");
if (level && !charging && !plugged) {
if ((level === "low" || level === "critical") && !charging && !pluggedIn) {
notify(device, level);
}
}
// Formerly known as maybeNotify
function notify(device, level) {
var name = getDeviceName(device);
var titleKey = level === "critical" ? "toast.battery.critical" : "toast.battery.low";
var descKey = level === "critical" ? "toast.battery.critical-desc" : "toast.battery.low-desc";
var title = I18n.tr(titleKey);
var desc = I18n.tr(descKey, {
"percent": getPercentage(device)
});
var desc = I18n.tr(descKey, {"percent": getPercentage(device)});
if (device == _bluetoothBattery && name) {
if (device == _bluetoothBattery && name) {
title = title + " " + name;
}
@@ -314,36 +303,24 @@ Singleton {
}
Instantiator {
model: laptopBatteries
model: deviceModel
delegate: Connections {
target: modelData
function onPercentageChanged() {
Logger.e("BatteryServiceDebug", "Check in progress... (Battery percentage changed)")
checkDevice(modelData)
}
function onStateChanged() {
Logger.e("BatteryServiceDebug", "Check in progress... (Battery state changed)")
checkDevice(modelData)
}
}
}
required property var modelData
property var device: findDevice(modelData.key)
target: device
Instantiator {
model: bluetoothBatteries
delegate: Connections {
target: modelData
function onPercentageChanged() {
Logger.e("BatteryServiceDebug", "Check in progress... (Bluetooth battery changed)")
checkDevice(modelData)
if (device.isLaptopBattery && modelData.key !== "__default__") {
return;
}
checkDevice(device)
}
function onStateChanged() {
Logger.e("BatteryServiceDebug", "Check in progress... (Bluetooth battery state changed)")
checkDevice(modelData)
}
function onConnected() {
Logger.e("BatteryServiceDebug", "Check in progress... (Bluetooth battery connected)")
checkDevice(modelData)
if (device.isLaptopBattery && modelData.key !== "__default__") {
return;
}
checkDevice(device)
}
}
}
}
}