mirror of
https://github.com/danbulant/dots-hyprland
synced 2026-05-19 04:08:48 +00:00
night light: use hyprsunset <- gammastep
This commit is contained in:
parent
3d5ed9401c
commit
574a2a11e7
7 changed files with 148 additions and 35 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# Bar, wallpaper
|
||||
exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh & gammastep
|
||||
exec-once = ~/.config/hypr/hyprland/scripts/start_geoclue_agent.sh
|
||||
exec-once = qs -c $qsConfig &
|
||||
|
||||
# Input method
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Singleton {
|
|||
id: root
|
||||
property string filePath: Directories.shellConfigPath
|
||||
property alias options: configOptionsJsonAdapter
|
||||
property bool ready: false
|
||||
|
||||
function setNestedValue(nestedKey, value) {
|
||||
let keys = nestedKey.split(".");
|
||||
|
|
@ -41,10 +42,10 @@ Singleton {
|
|||
|
||||
FileView {
|
||||
path: root.filePath
|
||||
|
||||
watchChanges: true
|
||||
onFileChanged: reload()
|
||||
onAdapterUpdated: writeAdapter()
|
||||
onLoaded: root.ready = true
|
||||
onLoadFailed: error => {
|
||||
if (error == FileViewError.FileNotFound) {
|
||||
writeAdapter();
|
||||
|
|
@ -171,6 +172,15 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
property JsonObject light: JsonObject {
|
||||
property JsonObject night: JsonObject {
|
||||
property bool automatic: true
|
||||
property string from: "19:00" // Format: "HH:mm", 24-hour time
|
||||
property string to: "06:30" // Format: "HH:mm", 24-hour time
|
||||
property int colorTemperature: 5000
|
||||
}
|
||||
}
|
||||
|
||||
property JsonObject networking: JsonObject {
|
||||
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,28 @@
|
|||
import QtQuick
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs
|
||||
import qs.services
|
||||
import Quickshell.Io
|
||||
|
||||
QuickToggleButton {
|
||||
id: nightLightButton
|
||||
property bool enabled: false
|
||||
property bool enabled: Hyprsunset.active
|
||||
toggled: enabled
|
||||
buttonIcon: "nightlight"
|
||||
buttonIcon: Config.options.light.night.automatic ? "night_sight_auto" : "bedtime"
|
||||
onClicked: {
|
||||
nightLightButton.enabled = !nightLightButton.enabled
|
||||
if (enabled) {
|
||||
nightLightOn.startDetached()
|
||||
}
|
||||
else {
|
||||
nightLightOff.startDetached()
|
||||
}
|
||||
Hyprsunset.toggle()
|
||||
}
|
||||
Process {
|
||||
id: nightLightOn
|
||||
command: ["gammastep"]
|
||||
|
||||
altAction: () => {
|
||||
Config.options.light.night.automatic = !Config.options.light.night.automatic
|
||||
}
|
||||
Process {
|
||||
id: nightLightOff
|
||||
command: ["pkill", "gammastep"]
|
||||
}
|
||||
Process {
|
||||
id: updateNightLightState
|
||||
running: true
|
||||
command: ["pidof", "gammastep"]
|
||||
stdout: SplitParser {
|
||||
onRead: (data) => { // if not empty then set toggled to true
|
||||
nightLightButton.enabled = data.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Hyprsunset.fetchState()
|
||||
}
|
||||
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Night Light")
|
||||
content: Translation.tr("Night Light | Right-click to toggle Auto mode")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,15 @@ pragma ComponentBehavior: Bound
|
|||
* A nice wrapper for date and time strings.
|
||||
*/
|
||||
Singleton {
|
||||
property var clock: SystemClock {
|
||||
id: clock
|
||||
precision: SystemClock.Minutes
|
||||
}
|
||||
property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm")
|
||||
property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM")
|
||||
property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy")
|
||||
property string uptime: "0h, 0m"
|
||||
|
||||
SystemClock {
|
||||
id: clock
|
||||
precision: SystemClock.Minutes
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 10
|
||||
running: true
|
||||
|
|
|
|||
117
.config/quickshell/ii/services/Hyprsunset.qml
Normal file
117
.config/quickshell/ii/services/Hyprsunset.qml
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import qs.modules.common
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
/**
|
||||
* Simple hyprsunset service with automatic mode.
|
||||
* In theory we don't need this because hyprsunset has a config file, but it somehow doesn't work.
|
||||
* It should also be possible to control it via hyprctl, but it doesn't work consistently either so we're just killing and launching.
|
||||
*/
|
||||
Singleton {
|
||||
id: root
|
||||
property var manualActive
|
||||
property string from: Config.options?.light?.night?.from ?? "19:00" // Default to 7 PM
|
||||
property string to: Config.options?.light?.night?.to ?? "06:30" // Default to 6:30 AM
|
||||
property bool automatic: Config.options?.light?.night?.automatic && (Config?.ready ?? true)
|
||||
property int colorTemperature: Config.options?.light?.night?.colorTemperature ?? 5000 // Default color temperature
|
||||
property bool shouldBeOn
|
||||
property bool firstEvaluation: true
|
||||
property bool active: false
|
||||
|
||||
property int fromHour: Number(from.split(":")[0])
|
||||
property int fromMinute: Number(from.split(":")[1])
|
||||
property int toHour: Number(to.split(":")[0])
|
||||
property int toMinute: Number(to.split(":")[1])
|
||||
|
||||
property int clockHour: DateTime.clock.hours
|
||||
property int clockMinute: DateTime.clock.minutes
|
||||
|
||||
|
||||
function isNoLater(hour1, minute1, hour2, minute2) {
|
||||
if (hour1 < hour2)
|
||||
return true;
|
||||
if (hour1 === hour2 && minute1 < minute2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
onClockMinuteChanged: reEvaluate()
|
||||
onAutomaticChanged: {
|
||||
root.manualActive = undefined;
|
||||
root.firstEvaluation = true;
|
||||
reEvaluate();
|
||||
}
|
||||
function reEvaluate() {
|
||||
const toHourIsNextDay = !isNoLater(fromHour, fromMinute, toHour, toMinute);
|
||||
const toHourWrapped = toHourIsNextDay ? toHour + 24 : toHour;
|
||||
const toMinuteWrapped = toMinute;
|
||||
root.shouldBeOn = isNoLater(fromHour, fromMinute, clockHour, clockMinute) && isNoLater(clockHour, clockMinute, toHourWrapped, toMinuteWrapped);
|
||||
if (firstEvaluation) {
|
||||
firstEvaluation = false;
|
||||
root.ensureState();
|
||||
}
|
||||
}
|
||||
|
||||
onShouldBeOnChanged: ensureState()
|
||||
function ensureState() {
|
||||
// console.log("[Hyprsunset] Ensuring state:", root.shouldBeOn, "Automatic mode:", root.automatic);
|
||||
if (!root.automatic || root.manualActive !== undefined)
|
||||
return;
|
||||
if (root.shouldBeOn) {
|
||||
root.enable();
|
||||
} else {
|
||||
root.disable();
|
||||
}
|
||||
}
|
||||
|
||||
function load() { } // Dummy to force init
|
||||
|
||||
function enable() {
|
||||
root.active = true;
|
||||
// console.log("[Hyprsunset] Enabling");
|
||||
Quickshell.execDetached(["bash", "-c", `pidof hyprsunset || hyprsunset --temperature ${root.colorTemperature}`]);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
root.active = false;
|
||||
// console.log("[Hyprsunset] Disabling");
|
||||
Quickshell.execDetached(["bash", "-c", `pkill hyprsunset`]);
|
||||
}
|
||||
|
||||
function fetchState() {
|
||||
fetchProc.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: fetchProc
|
||||
running: true
|
||||
command: ["bash", "-c", "hyprctl hyprsunset temperature"]
|
||||
stdout: StdioCollector {
|
||||
id: stateCollector
|
||||
onStreamFinished: {
|
||||
const output = stateCollector.text.trim();
|
||||
if (output.length == 0 || output.startsWith("Couldn't"))
|
||||
root.active = false;
|
||||
else
|
||||
root.active = (output != "6500");
|
||||
// console.log("[Hyprsunset] Fetched state:", output, "->", root.active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (root.manualActive === undefined)
|
||||
root.manualActive = root.active;
|
||||
|
||||
root.manualActive = !root.manualActive;
|
||||
if (root.manualActive) {
|
||||
root.enable();
|
||||
} else {
|
||||
root.disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,9 +49,10 @@ ShellRoot {
|
|||
|
||||
// Force initialization of some singletons
|
||||
Component.onCompleted: {
|
||||
MaterialThemeLoader.reapplyTheme()
|
||||
Cliphist.refresh()
|
||||
FirstRunExperience.load()
|
||||
Hyprsunset.load()
|
||||
MaterialThemeLoader.reapplyTheme()
|
||||
}
|
||||
|
||||
LazyLoader { active: enableBar; component: Bar {} }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ pkgdesc='Illogical Impulse Backlight Dependencies'
|
|||
arch=(any)
|
||||
license=(None)
|
||||
depends=(
|
||||
gammastep
|
||||
geoclue
|
||||
brightnessctl
|
||||
ddcutil
|
||||
|
|
|
|||
Loading…
Reference in a new issue