From 9e48d9658b24bb05d38e66c5a997c62809428d77 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 20 May 2026 15:31:28 +0200 Subject: [PATCH] Add Night Light bar indicator --- bin/omarchy-toggle-nightlight | 30 ++++++++- migrations/1779283409.sh | 70 +++++++++++++++++++++ shell/plugins/bar/indicators/nightlight.qml | 64 +++++++++++++++++++ shell/plugins/settings/SettingsPanel.qml | 2 +- shell/shell-defaults.json | 1 + 5 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 migrations/1779283409.sh create mode 100644 shell/plugins/bar/indicators/nightlight.qml diff --git a/bin/omarchy-toggle-nightlight b/bin/omarchy-toggle-nightlight index 52ecfa19..2b3b5f0e 100755 --- a/bin/omarchy-toggle-nightlight +++ b/bin/omarchy-toggle-nightlight @@ -1,22 +1,48 @@ #!/bin/bash # omarchy:summary=Toggle nightlight screen temperature +# omarchy:args=[--status] # omarchy:examples=omarchy toggle nightlight ON_TEMP=4000 OFF_TEMP=6000 +current_temp() { + hyprctl hyprsunset temperature 2>/dev/null | grep -oE '[0-9]+' | head -n1 +} + +status_json() { + local temp enabled + + temp=$(current_temp) + if [[ -n $temp && $temp != $OFF_TEMP ]]; then + enabled=true + else + enabled=false + fi + + jq -cn --argjson enabled "$enabled" --arg temp "$temp" \ + '{enabled:$enabled, temperature:(($temp | tonumber?) // null)}' +} + +if [[ ${1:-} == "--status" ]]; then + status_json + exit 0 +fi + # Ensure hyprsunset is running -if ! pgrep -x hyprsunset; then +if ! pgrep -x hyprsunset >/dev/null; then setsid uwsm-app -- hyprsunset & sleep 1 # Give it time to register fi # Query the current temperature -CURRENT_TEMP=$(hyprctl hyprsunset temperature 2>/dev/null | grep -oE '[0-9]+') +CURRENT_TEMP=$(current_temp) if [[ $CURRENT_TEMP == $OFF_TEMP ]]; then hyprctl hyprsunset temperature $ON_TEMP else hyprctl hyprsunset temperature $OFF_TEMP fi + +omarchy-shell -q bar refreshIndicators >/dev/null 2>&1 || true diff --git a/migrations/1779283409.sh b/migrations/1779283409.sh new file mode 100644 index 00000000..47b94a7b --- /dev/null +++ b/migrations/1779283409.sh @@ -0,0 +1,70 @@ +echo "Add Night Light to the default bar indicator list" + +config_file="$HOME/.config/omarchy/shell.json" + +if [[ -f $config_file ]] && omarchy-cmd-present jq; then + tmp=$(mktemp) + jq ' + def indicator_id: + if type == "string" then + . + elif type == "object" then + (.id // "") + else + "" + end; + + def has_indicator($id): + any(.[]?; indicator_id == $id); + + def indicator_index($id): + [range(0; length) as $i | select((.[$i] | indicator_id) == $id) | $i][0]; + + def nightlight_entry: + if any(.[]?; type == "object") then + { id: "nightlight" } + else + "nightlight" + end; + + def add_nightlight: + if type != "array" or has_indicator("nightlight") then + . + else + (indicator_index("dnd")) as $dnd_index | + if $dnd_index == null then + . + else + .[0:$dnd_index + 1] + [nightlight_entry] + .[$dnd_index + 1:] + end + end; + + .bar.layout |= ( + if type == "object" then + with_entries( + .value |= ( + if type == "array" then + map( + if type == "object" and .id == "indicators" then + if (.items | type) == "array" then + .items |= add_nightlight + elif (.indicators | type) == "array" then + .indicators |= add_nightlight + else + . + end + else + . + end + ) + else + . + end + ) + ) + else + . + end + ) + ' "$config_file" >"$tmp" && mv "$tmp" "$config_file" || rm -f "$tmp" +fi diff --git a/shell/plugins/bar/indicators/nightlight.qml b/shell/plugins/bar/indicators/nightlight.qml new file mode 100644 index 00000000..7aa67da5 --- /dev/null +++ b/shell/plugins/bar/indicators/nightlight.qml @@ -0,0 +1,64 @@ +import QtQuick +import Quickshell.Io +import qs.Ui + +BarIndicator { + id: root + + property bool nightlight: false + + active: nightlight + activeText: "󰔎" + inactiveText: "󰔎" + activeTooltipText: "Night Light on" + inactiveTooltipText: "Night Light" + + function refresh() { + if (!statusProc.running) statusProc.running = true + } + + function update(raw) { + var data = extractData(raw) + nightlight = data && data.enabled === true + } + + function toggle() { + if (root.bar) root.bar.run("omarchy-toggle-nightlight") + refreshTimer.restart() + } + + Component.onCompleted: refresh() + + Connections { + target: root.bar + ignoreUnknownSignals: true + function onIndicatorsRefreshRequested() { root.refresh() } + } + + Process { + id: statusProc + command: ["omarchy-toggle-nightlight", "--status"] + stdout: StdioCollector { + waitForEnd: true + onStreamFinished: root.update(text) + } + onExited: function(exitCode) { + if (exitCode !== 0) root.nightlight = false + } + } + + Timer { + id: refreshTimer + interval: 1500 + onTriggered: root.refresh() + } + + Timer { + interval: 5000 + running: true + repeat: true + onTriggered: root.refresh() + } + + onPressed: function() { root.toggle() } +} diff --git a/shell/plugins/settings/SettingsPanel.qml b/shell/plugins/settings/SettingsPanel.qml index c89b4327..d832cc08 100644 --- a/shell/plugins/settings/SettingsPanel.qml +++ b/shell/plugins/settings/SettingsPanel.qml @@ -133,7 +133,7 @@ Item { left: [{ id: "omarchy" }, { id: "workspaces" }], center: [ { id: "calendar", format: "dddd HH:mm", formatAlt: "dd MMMM 'W'ww yyyy", verticalFormat: "HH\n\u2014\nmm" }, - { id: "weather" }, { id: "indicators", items: [ "dnd", "stayAwake", "screenrecording", "dictation" ] }, { id: "update" } + { id: "weather" }, { id: "indicators", items: [ "dnd", "nightlight", "stayAwake", "screenrecording", "dictation" ] }, { id: "update" } ], right: [ { id: "tray" }, { id: "bluetoothPanel" }, { id: "networkPanel" }, diff --git a/shell/shell-defaults.json b/shell/shell-defaults.json index 0455eb22..6b0b9546 100644 --- a/shell/shell-defaults.json +++ b/shell/shell-defaults.json @@ -31,6 +31,7 @@ "id": "indicators", "items": [ "dnd", + "nightlight", "stayAwake", "screenrecording", "dictation"