diff --git a/bin/omarchy-battery-low b/bin/omarchy-battery-low new file mode 100755 index 00000000..bc06e1ac --- /dev/null +++ b/bin/omarchy-battery-low @@ -0,0 +1,22 @@ +#!/bin/bash + +# omarchy:summary=Send the low battery warning notification and run battery-low hooks. +# omarchy:args= +# omarchy:hidden=true + +set -euo pipefail + +if (($# != 1)); then + echo "Usage: omarchy-battery-low " >&2 + exit 1 +fi + +level=$1 + +if [[ ! $level =~ ^[0-9]+$ ]]; then + echo "Battery percentage must be a number" >&2 + exit 1 +fi + +omarchy-notification-send -g "󱐋" -u critical "Time to recharge!" "Battery is down to ${level}%" -i battery-caution -t 30000 +omarchy-hook battery-low "$level" diff --git a/bin/omarchy-battery-monitor b/bin/omarchy-battery-monitor deleted file mode 100755 index 1238791e..00000000 --- a/bin/omarchy-battery-monitor +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# omarchy:summary=Designed to be run by systemd timer every 30 seconds and alerts if battery is low -# omarchy:hidden=true - -BATTERY_THRESHOLD=10 -NOTIFICATION_FLAG="/run/user/$UID/omarchy_battery_notified" -BATTERY_LEVEL=$(omarchy-battery-remaining) -BATTERY_STATE=$(upower -i $(upower -e | grep 'BAT') | grep -E "state" | awk '{print $2}') - -send_notification() { - notify-send -u critical "󱐋 Time to recharge!" "Battery is down to ${1}%" -i battery-caution -t 30000 - omarchy-hook battery-low "$1" -} - -if [[ -n $BATTERY_LEVEL && $BATTERY_LEVEL =~ ^[0-9]+$ ]]; then - if [[ $BATTERY_STATE == "discharging" ]] && (( BATTERY_LEVEL <= BATTERY_THRESHOLD )); then - if [[ ! -f $NOTIFICATION_FLAG ]]; then - send_notification $BATTERY_LEVEL - touch $NOTIFICATION_FLAG - fi - else - rm -f $NOTIFICATION_FLAG - fi -fi diff --git a/bin/omarchy-first-run b/bin/omarchy-first-run index cf214dc0..be2c9685 100755 --- a/bin/omarchy-first-run +++ b/bin/omarchy-first-run @@ -10,7 +10,6 @@ FIRST_RUN_MODE=~/.local/state/omarchy/first-run.mode if [[ -f $FIRST_RUN_MODE ]]; then rm -f "$FIRST_RUN_MODE" - bash "$OMARCHY_PATH/install/first-run/battery-monitor.sh" bash "$OMARCHY_PATH/install/first-run/recover-internal-monitor.sh" bash "$OMARCHY_PATH/install/first-run/cleanup-reboot-sudoers.sh" bash "$OMARCHY_PATH/install/first-run/firewall.sh" diff --git a/config/systemd/user/omarchy-battery-monitor.service b/config/systemd/user/omarchy-battery-monitor.service deleted file mode 100644 index 6e2e8e99..00000000 --- a/config/systemd/user/omarchy-battery-monitor.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Omarchy Battery Monitor Check -After=graphical-session.target - -[Service] -Type=oneshot -ExecStart=%h/.local/share/omarchy/bin/omarchy-battery-monitor -Environment=DISPLAY=:0 -LogLevelMax=warning diff --git a/config/systemd/user/omarchy-battery-monitor.timer b/config/systemd/user/omarchy-battery-monitor.timer deleted file mode 100644 index dc43763e..00000000 --- a/config/systemd/user/omarchy-battery-monitor.timer +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Omarchy Battery Monitor Timer -Requires=omarchy-battery-monitor.service - -[Timer] -OnBootSec=1min -OnUnitActiveSec=30sec -AccuracySec=10sec - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/install/first-run/battery-monitor.sh b/install/first-run/battery-monitor.sh deleted file mode 100644 index a8f05522..00000000 --- a/install/first-run/battery-monitor.sh +++ /dev/null @@ -1,8 +0,0 @@ -if omarchy-battery-present; then - powerprofilesctl set balanced || true - - # Enable battery monitoring timer for low battery notifications - systemctl --user enable --now omarchy-battery-monitor.timer -else - powerprofilesctl set performance || true -fi diff --git a/migrations/1752168292.sh b/migrations/1752168292.sh deleted file mode 100644 index 0f529134..00000000 --- a/migrations/1752168292.sh +++ /dev/null @@ -1,10 +0,0 @@ -echo "Enable battery low notifications for laptops" - -if ls /sys/class/power_supply/BAT* &>/dev/null && [[ ! -f ~/.local/share/omarchy/config/systemd/user/omarchy-battery-monitor.service ]]; then - mkdir -p ~/.config/systemd/user - - cp ~/.local/share/omarchy/config/systemd/user/omarchy-battery-monitor.* ~/.config/systemd/user/ - - systemctl --user daemon-reload - systemctl --user enable --now omarchy-battery-monitor.timer || true -fi diff --git a/migrations/1779218170.sh b/migrations/1779218170.sh new file mode 100644 index 00000000..9a76cb1a --- /dev/null +++ b/migrations/1779218170.sh @@ -0,0 +1,5 @@ +echo "Move low battery notifications into omarchy-shell" + +systemctl --user disable --now omarchy-battery-monitor.timer 2>/dev/null || true +rm -f "$HOME/.config/systemd/user/omarchy-battery-monitor.service" "$HOME/.config/systemd/user/omarchy-battery-monitor.timer" +systemctl --user daemon-reload 2>/dev/null || true diff --git a/shell/plugins/README.md b/shell/plugins/README.md index 106355c8..d4f7fa7b 100644 --- a/shell/plugins/README.md +++ b/shell/plugins/README.md @@ -19,6 +19,7 @@ User-installed plugins live alongside these conceptually but on disk under | Clipboard mgr | `omarchy.clipboard-picker`| `overlay` | `clipboard-picker/ClipboardPicker.qml`| | Omarchy menu | `omarchy.menu` | `menu` | `menu/Menu.qml` | | Notifications | `omarchy.notifications` | `service` | `notifications/Service.qml` | +| Battery mon. | `omarchy.battery-monitor` | `service` | `battery-monitor/Service.qml` | | Idle monitor | `omarchy.idle` | `service` | `idle/Service.qml` | | Lock screen | `omarchy.lock` | `service` | `lock/Service.qml` | | OSD | `omarchy.osd` | `panel` | `osd/Osd.qml` | diff --git a/shell/plugins/battery-monitor/Service.qml b/shell/plugins/battery-monitor/Service.qml new file mode 100644 index 00000000..c0459800 --- /dev/null +++ b/shell/plugins/battery-monitor/Service.qml @@ -0,0 +1,73 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Services.UPower + +Item { + id: root + + property var shell: null + property string omarchyPath: Quickshell.env("OMARCHY_PATH") + + readonly property int batteryThreshold: 10 + + PersistentProperties { + id: persisted + reloadableId: "omarchy-battery-monitor" + property bool notifiedLowBattery: false + } + + function batteryPercentage() { + var device = UPower.displayDevice + if (!device || !device.isPresent) return -1 + return Math.round(Number(device.percentage || 0) * 100) + } + + function isDischarging() { + var device = UPower.displayDevice + return !!(device && device.isPresent + && UPower.onBattery + && device.state === UPowerDeviceState.Discharging) + } + + function checkBattery() { + var level = batteryPercentage() + if (level < 0) { + persisted.notifiedLowBattery = false + return + } + + if (isDischarging() && level <= batteryThreshold) { + if (!persisted.notifiedLowBattery) { + persisted.notifiedLowBattery = true + sendLowBatteryWarning(level) + } + } else { + persisted.notifiedLowBattery = false + } + } + + function sendLowBatteryWarning(level) { + if (warningProcess.running) return + warningProcess.command = [ + "omarchy-battery-low", + String(level) + ] + warningProcess.running = true + } + + Process { id: warningProcess } + + Timer { + interval: 30000 + running: true + repeat: true + triggeredOnStart: true + onTriggered: root.checkBattery() + } + + Connections { + target: UPower + function onOnBatteryChanged() { root.checkBattery() } + } +} diff --git a/shell/plugins/battery-monitor/manifest.json b/shell/plugins/battery-monitor/manifest.json new file mode 100644 index 00000000..69ac4a14 --- /dev/null +++ b/shell/plugins/battery-monitor/manifest.json @@ -0,0 +1,14 @@ +{ + "schemaVersion": 1, + "id": "omarchy.battery-monitor", + "name": "Battery Monitor", + "version": "1.0.0", + "author": "Omarchy", + "description": "Low battery warning service", + "kinds": [ + "service" + ], + "entryPoints": { + "service": "Service.qml" + } +} diff --git a/shell/plugins/notifications/Service.qml b/shell/plugins/notifications/Service.qml index 1e4c471e..96dcaec4 100644 --- a/shell/plugins/notifications/Service.qml +++ b/shell/plugins/notifications/Service.qml @@ -108,11 +108,10 @@ Item { // - omarchy-action: a user-action confirmation toast ("Theme changed", // "Screenshot saved"). The user JUST did something — their feedback // should show. - // - urgency=critical AND app_name=notify-send: bare-CLI emergency alerts - // (omarchy-battery-monitor uses this for low-battery; a few scripts - // use it for emergency failures). Trusted because it's almost always - // omarchy or system shell scripts — chat apps set app_name to - // their brand (Discord/Slack/Vesktop) which falls outside this rule. + // - urgency=critical AND app_name=notify-send: bare-CLI emergency alerts. + // Trusted because it's almost always omarchy or system shell scripts — + // chat apps set app_name to their brand (Discord/Slack/Vesktop), which + // falls outside this rule. function shouldBypassDnd(notification) { var appName = String(notification.appName || "") if (appName === "omarchy-action") return true