1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-11 07:52:50 -05:00

night mode repairs

This commit is contained in:
bbedward
2025-08-29 14:23:37 -04:00
parent 3746b1cfad
commit 108fdd9b7f
9 changed files with 651 additions and 947 deletions

View File

@@ -5,7 +5,6 @@ import QtQuick
import Quickshell
import Quickshell.Io
import qs.Common
import qs.Services
Singleton {
id: root
@@ -33,7 +32,18 @@ Singleton {
signal brightnessChanged
signal deviceSwitched
property bool nightModeActive: false
property bool nightModeActive: nightModeEnabled
// Night Mode Properties
property bool nightModeEnabled: false
property bool automationAvailable: false
property bool geoclueAvailable: false
property bool isAutomaticNightTime: false
function buildGammastepCommand(gammastepArgs) {
const commandStr = "pkill gammastep; " + ["gammastep"].concat(gammastepArgs).join(" ")
return ["sh", "-c", commandStr]
}
function setBrightnessInternal(percentage, device) {
const clampedValue = Math.max(1, Math.min(100, percentage))
@@ -214,58 +224,211 @@ Singleton {
ddcInitialBrightnessProcess.running = true
}
// Night Mode Functions - Simplified
function enableNightMode() {
if (nightModeActive)
if (!automationAvailable) {
gammaStepTestProcess.running = true
return
}
// Test if gammastep exists before enabling
gammaStepTestProcess.running = true
}
function updateNightModeTemperature(temperature) {
SessionData.setNightModeTemperature(temperature)
// If night mode is active, restart it with new temperature
if (nightModeActive) {
// Temporarily disable and re-enable to restart with new temp
nightModeActive = false
Qt.callLater(() => {
if (SessionData.nightModeEnabled) {
nightModeActive = true
}
})
nightModeEnabled = true
SessionData.setNightModeEnabled(true)
// Apply immediately or start automation
if (SessionData.nightModeAutoEnabled) {
startAutomation()
} else {
applyNightModeDirectly()
}
}
function disableNightMode() {
nightModeActive = false
nightModeEnabled = false
SessionData.setNightModeEnabled(false)
// Also kill any stray gammastep processes
Quickshell.execDetached(["pkill", "gammastep"])
stopAutomation()
// Nuclear approach - kill ALL gammastep processes multiple times
Quickshell.execDetached(["pkill", "-f", "gammastep"])
Quickshell.execDetached(["pkill", "-9", "gammastep"])
Quickshell.execDetached(["killall", "gammastep"])
// Also stop all related processes
gammaStepProcess.running = false
automationProcess.running = false
gammaStepTestProcess.running = false
}
function toggleNightMode() {
// Check if automation is active - show warning if trying to manually toggle
if (SessionData.nightModeAutoEnabled) {
ToastService.showWarning("Night mode is in automatic mode. Disable automation in settings to control manually.")
return
}
if (nightModeActive) {
if (nightModeEnabled) {
disableNightMode()
} else {
enableNightMode()
}
}
function applyNightModeDirectly() {
const temperature = SessionData.nightModeTemperature || 4500
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-O", String(temperature)
])
gammaStepProcess.running = true
}
function resetToNormalMode() {
// Just kill gammastep to return to normal display temperature
Quickshell.execDetached(["pkill", "gammastep"])
}
function startAutomation() {
if (!automationAvailable) return
const mode = SessionData.nightModeAutoMode || "time"
switch (mode) {
case "time":
startTimeBasedMode()
break
case "location":
startLocationBasedMode()
break
}
}
function stopAutomation() {
automationProcess.running = false
gammaStepProcess.running = false
isAutomaticNightTime = false
// Nuclear approach - kill ALL gammastep processes multiple times
Quickshell.execDetached(["pkill", "-f", "gammastep"])
Quickshell.execDetached(["pkill", "-9", "gammastep"])
Quickshell.execDetached(["killall", "gammastep"])
}
function startTimeBasedMode() {
checkTimeBasedMode()
}
function startLocationBasedMode() {
const temperature = SessionData.nightModeTemperature || 4500
const dayTemp = 6500
if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
automationProcess.command = buildGammastepCommand([
"-m", "wayland",
"-l", `${SessionData.latitude.toFixed(6)}:${SessionData.longitude.toFixed(6)}`,
"-t", `${dayTemp}:${temperature}`,
"-v"
])
automationProcess.running = true
return
}
if (SessionData.nightModeLocationProvider === "geoclue2") {
automationProcess.command = buildGammastepCommand([
"-m", "wayland",
"-l", "geoclue2",
"-t", `${dayTemp}:${temperature}`,
"-v"
])
automationProcess.running = true
return
}
console.warn("DisplayService: Location mode selected but no coordinates or geoclue provider set")
}
function checkTimeBasedMode() {
if (!nightModeEnabled || !SessionData.nightModeAutoEnabled || SessionData.nightModeAutoMode !== "time") {
return
}
const now = new Date()
const currentTime = now.getHours() * 60 + now.getMinutes()
const startMinutes = SessionData.nightModeStartHour * 60 + SessionData.nightModeStartMinute
const endMinutes = SessionData.nightModeEndHour * 60 + SessionData.nightModeEndMinute
let shouldBeNight = false
if (startMinutes > endMinutes) {
shouldBeNight = (currentTime >= startMinutes) || (currentTime < endMinutes)
} else {
shouldBeNight = (currentTime >= startMinutes) && (currentTime < endMinutes)
}
if (shouldBeNight !== isAutomaticNightTime) {
isAutomaticNightTime = shouldBeNight
if (shouldBeNight) {
applyNightModeDirectly()
} else {
resetToNormalMode()
}
}
}
function detectLocationProviders() {
geoclueDetectionProcess.running = true
}
function setNightModeAutomationMode(mode) {
console.log("DisplayService: Setting night mode automation mode to:", mode)
SessionData.setNightModeAutoMode(mode)
}
function evaluateNightMode() {
console.log("DisplayService: Evaluating night mode state - enabled:", nightModeEnabled, "auto:", SessionData.nightModeAutoEnabled)
// Always stop all processes first to clean slate
stopAutomation()
if (!nightModeEnabled) {
return
}
if (SessionData.nightModeAutoEnabled) {
restartTimer.nextAction = "automation"
restartTimer.start()
} else {
restartTimer.nextAction = "direct"
restartTimer.start()
}
}
function checkNightModeAvailability() {
gammastepAvailabilityProcess.running = true
}
Timer {
id: restartTimer
property string nextAction: ""
interval: 100
repeat: false
onTriggered: {
if (nextAction === "automation") {
startAutomation()
} else if (nextAction === "direct") {
applyNightModeDirectly()
}
nextAction = ""
}
}
Component.onCompleted: {
ddcDetectionProcess.running = true
refreshDevices()
checkNightModeAvailability()
// Check if night mode was enabled on startup
if (SessionData.nightModeEnabled) {
enableNightMode()
// Initialize night mode state from session
nightModeEnabled = SessionData.nightModeEnabled
}
SystemClock {
precision: SystemClock.Minutes
onDateChanged: {
if (nightModeEnabled && SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "time") {
checkTimeBasedMode()
}
}
}
@@ -393,27 +556,11 @@ Singleton {
"max": parseInt(parts[4])
})
}
// Store brightnessctl devices separately, will be combined with DDC
const brightnessCtlDevices = newDevices
devices = brightnessCtlDevices
// If we have DDC devices, combine them
if (ddcDevices.length > 0) {
refreshDevicesInternal()
} else if (devices.length > 0 && !currentDevice) {
// Try to restore last selected device, fallback to first device
const lastDevice = SessionData.lastBrightnessDevice || ""
const deviceExists = devices.some(
d => d.name === lastDevice)
if (deviceExists) {
setCurrentDevice(lastDevice, false)
} else {
const nonKbdDevice = devices.find(
d => !d.name.includes("kbd"))
|| devices[0]
setCurrentDevice(nonKbdDevice.name, false)
}
}
// Store brightnessctl devices separately
devices = newDevices
// Always refresh to combine with DDC devices and set up device selection
refreshDevicesInternal()
}
}
}
@@ -564,46 +711,108 @@ Singleton {
}
Process {
id: gammaStepTestProcess
id: gammastepAvailabilityProcess
command: ["which", "gammastep"]
running: false
onExited: function(exitCode) {
automationAvailable = (exitCode === 0)
if (automationAvailable) {
console.log("DisplayService: gammastep available")
detectLocationProviders()
// If night mode should be enabled on startup
if (nightModeEnabled && SessionData.nightModeAutoEnabled) {
startAutomation()
} else if (nightModeEnabled) {
applyNightModeDirectly()
}
} else {
console.log("DisplayService: gammastep not available")
}
}
}
Process {
id: geoclueDetectionProcess
command: ["sh", "-c", "busctl --system list | grep -qF org.freedesktop.GeoClue2"]
running: false
onExited: function (exitCode) {
geoclueAvailable = (exitCode === 0)
console.log("DisplayService: geoclue available:", geoclueAvailable)
}
}
Process {
id: gammaStepTestProcess
command: ["which", "gammastep"]
running: false
onExited: function (exitCode) {
if (exitCode === 0) {
// gammastep exists, enable night mode
nightModeActive = true
automationAvailable = true
nightModeEnabled = true
SessionData.setNightModeEnabled(true)
if (SessionData.nightModeAutoEnabled) {
startAutomation()
} else {
applyNightModeDirectly()
}
} else {
// gammastep not found
console.warn("DisplayService: gammastep not found")
ToastService.showWarning(
"Night mode failed: gammastep not found")
ToastService.showWarning("Night mode failed: gammastep not found")
}
}
}
Process {
id: gammaStepProcess
command: {
const temperature = SessionData.nightModeTemperature || 4500
return ["gammastep", "-m", "wayland", "-O", String(temperature)]
}
running: nightModeActive
running: false
onExited: function (exitCode) {
// If process exits with non-zero code while we think it should be running
if (nightModeActive && exitCode !== 0) {
console.warn("DisplayService: Night mode process crashed with exit code:",
exitCode)
nightModeActive = false
SessionData.setNightModeEnabled(false)
ToastService.showWarning("Night mode failed: process crashed")
if (nightModeEnabled && exitCode !== 0 && exitCode !== 15) {
console.warn("DisplayService: Night mode process failed:", exitCode)
}
}
}
Process {
id: automationProcess
running: false
property string processType: "automation"
onExited: function (exitCode) {
if (nightModeEnabled && SessionData.nightModeAutoEnabled && exitCode !== 0 && exitCode !== 15) {
console.warn("DisplayService: Night mode automation failed:", exitCode)
// Location mode failed
console.warn("DisplayService: Location-based night mode failed")
}
}
}
// Session Data Connections
Connections {
target: SessionData
function onNightModeEnabledChanged() {
nightModeEnabled = SessionData.nightModeEnabled
evaluateNightMode()
}
function onNightModeAutoEnabledChanged() { evaluateNightMode() }
function onNightModeAutoModeChanged() { evaluateNightMode() }
function onNightModeStartHourChanged() { evaluateNightMode() }
function onNightModeStartMinuteChanged() { evaluateNightMode() }
function onNightModeEndHourChanged() { evaluateNightMode() }
function onNightModeEndMinuteChanged() { evaluateNightMode() }
function onNightModeTemperatureChanged() { evaluateNightMode() }
function onLatitudeChanged() { evaluateNightMode() }
function onLongitudeChanged() { evaluateNightMode() }
function onNightModeLocationProviderChanged() { evaluateNightMode() }
}
// IPC Handler for external control
IpcHandler {
function set(percentage: string, device: string): string {
@@ -702,9 +911,9 @@ Singleton {
if (!root.brightnessAvailable)
return "No brightness devices available"
let result = "Available devices:\n"
let result = "Available devices:\\n"
for (const device of root.devices) {
result += device.name + " (" + device.class + ")\n"
result += device.name + " (" + device.class + ")\\n"
}
return result
}
@@ -716,7 +925,7 @@ Singleton {
IpcHandler {
function toggle(): string {
root.toggleNightMode()
return root.nightModeActive ? "Night mode enabled" : "Night mode disabled"
return root.nightModeEnabled ? "Night mode enabled" : "Night mode disabled"
}
function enable(): string {
@@ -730,7 +939,7 @@ Singleton {
}
function status(): string {
return root.nightModeActive ? "Night mode is enabled" : "Night mode is disabled"
return root.nightModeEnabled ? "Night mode is enabled" : "Night mode is disabled"
}
function temperature(value: string): string {
@@ -753,12 +962,13 @@ Singleton {
SessionData.setNightModeTemperature(rounded)
// If night mode is active, restart it with new temperature
if (root.nightModeActive) {
root.nightModeActive = false
Qt.callLater(() => {
root.nightModeActive = true
})
// Restart night mode with new temperature if active
if (root.nightModeEnabled) {
if (SessionData.nightModeAutoEnabled) {
root.startAutomation()
} else {
root.applyNightModeDirectly()
}
}
if (rounded !== temp) {
@@ -770,4 +980,4 @@ Singleton {
target: "night"
}
}
}

View File

@@ -1,505 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import qs.Common
Singleton {
id: root
property bool automationAvailable: false
property bool locationProviderAvailable: false
property var availableProviders: []
property string currentProvider: ""
property bool isAutomaticNightTime: false
property string currentLocation: ""
property real latitude: 0.0
property real longitude: 0.0
function testGeoclueConnection() {
geoclueTestProcess.running = false
geoclueTestProcess.command = [
"timeout", "32",
"gammastep",
"-m", "wayland",
"-l", "geoclue2",
"-O", "6500",
"-v"
]
geoclueTestProcess.running = true
}
Component.onCompleted: {
checkAvailability()
updateFromSessionData()
if (typeof globalThis !== 'undefined') {
globalThis.testNightMode = manualNightModeTest
globalThis.resetNightMode = manualResetTest
globalThis.clearNightModeLocation = clearLocation
globalThis.nightModeService = root
}
}
function checkAvailability() {
gammaStepTestProcess.running = true
}
function startAutomation() {
if (!automationAvailable) {
console.warn("NightModeAutomationService: Gammastep not available")
return
}
// Stop any existing automation processes first
stopAutomation()
const mode = SessionData.nightModeAutoMode || "manual"
switch (mode) {
case "time":
startTimeBasedMode()
break
case "location":
startLocationBasedMode()
break
case "manual":
default:
stopAutomation()
break
}
}
function stopAutomation() {
// Stop the unified process
gammaStepProcess.running = false
isAutomaticNightTime = false
}
function startTimeBasedMode() {
checkTimeBasedMode()
}
function startLocationBasedMode() {
gammaStepProcess.running = false
const temperature = SessionData.nightModeTemperature || 4500
const dayTemp = 6500
gammaStepProcess.processType = "automation"
if (latitude !== 0.0 && longitude !== 0.0) {
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-l", `${latitude.toFixed(6)}:${longitude.toFixed(6)}`,
"-t", `${dayTemp}:${temperature}`,
"-v"
])
gammaStepProcess.running = true
return
}
// Check if location providers are available
if (!locationProviderAvailable) {
console.warn("NightModeAutomationService: No location provider available, falling back to time-based mode")
SessionData.setNightModeAutoMode("time")
startTimeBasedMode()
return
}
if (currentProvider === "geoclue2") {
const temperature = SessionData.nightModeTemperature || 4500
const dayTemp = 6500
gammaStepProcess.processType = "automation"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-l", "geoclue2",
"-t", `${dayTemp}:${temperature}`,
"-v"
])
gammaStepProcess.running = true
return
} else {
console.warn("NightModeAutomationService: No working location provider, falling back to time-based mode")
SessionData.setNightModeAutoMode("time")
startTimeBasedMode()
return
}
}
function checkTimeBasedMode() {
if (!SessionData.nightModeAutoEnabled || SessionData.nightModeAutoMode !== "time") {
return
}
const now = new Date()
const currentHour = now.getHours()
const currentMinute = now.getMinutes()
const currentTime = currentHour * 60 + currentMinute
const startTime = SessionData.nightModeStartTime || "20:00"
const endTime = SessionData.nightModeEndTime || "06:00"
const startParts = startTime.split(":")
const endParts = endTime.split(":")
const startMinutes = parseInt(startParts[0]) * 60 + parseInt(startParts[1])
const endMinutes = parseInt(endParts[0]) * 60 + parseInt(endParts[1])
let shouldBeNight = false
if (startMinutes > endMinutes) {
shouldBeNight = (currentTime >= startMinutes) || (currentTime < endMinutes)
} else {
shouldBeNight = (currentTime >= startMinutes) && (currentTime < endMinutes)
}
if (shouldBeNight !== isAutomaticNightTime) {
isAutomaticNightTime = shouldBeNight
if (shouldBeNight) {
requestNightModeActivation()
} else {
requestNightModeDeactivation()
}
}
}
function requestNightModeActivation() {
const temperature = SessionData.nightModeTemperature || 4500
gammaStepProcess.running = false
gammaStepProcess.processType = "activate"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-O", String(temperature)
])
gammaStepProcess.running = true
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode !== "manual") {
SessionData.setNightModeEnabled(true)
}
}
function requestNightModeDeactivation() {
gammaStepProcess.running = false
gammaStepProcess.processType = "reset"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-O", "6500"
])
gammaStepProcess.running = true
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode !== "manual") {
SessionData.setNightModeEnabled(false)
}
}
function setLocation(lat, lon) {
latitude = lat
longitude = lon
currentLocation = `${lat.toFixed(6)},${lon.toFixed(6)}`
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "location") {
startLocationBasedMode()
}
}
function clearLocation() {
latitude = 0.0
longitude = 0.0
currentLocation = ""
SessionData.setLatitude(0.0)
SessionData.setLongitude(0.0)
SessionData.saveSettings()
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "location") {
startLocationBasedMode()
}
}
function buildGammastepCommand(gammastepArgs) {
const commandStr = "pkill gammastep; " + ["gammastep"].concat(gammastepArgs).join(" ")
return ["sh", "-c", commandStr]
}
function updateFromSessionData() {
if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) {
setLocation(SessionData.latitude, SessionData.longitude)
} else {
latitude = 0.0
longitude = 0.0
currentLocation = ""
}
}
function detectLocationProviders() {
locationProviderDetectionProcess.running = true
}
function manualNightModeTest() {
const temperature = SessionData.nightModeTemperature || 4500
gammaStepProcess.running = false
gammaStepProcess.processType = "test"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-O", String(temperature)
])
gammaStepProcess.running = true
testFeedbackTimer.interval = 2000
testFeedbackTimer.feedbackMessage = "Night mode test applied"
testFeedbackTimer.start()
}
function manualResetTest() {
gammaStepProcess.running = false
gammaStepProcess.processType = "test"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-O", "6500"
])
gammaStepProcess.running = true
testFeedbackTimer.interval = 2000
testFeedbackTimer.feedbackMessage = "Screen reset to normal temperature"
testFeedbackTimer.start()
}
SystemClock {
id: systemClock
precision: SystemClock.Minutes
onDateChanged: {
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "time") {
checkTimeBasedMode()
}
}
}
Process {
id: gammaStepTestProcess
command: ["which", "gammastep"]
running: false
onExited: function(exitCode) {
automationAvailable = (exitCode === 0)
if (automationAvailable) {
detectLocationProviders()
if (SessionData.nightModeAutoEnabled) {
startAutomation()
}
}
}
}
Process {
id: locationProviderDetectionProcess
command: ["gammastep", "-l", "list"]
running: false
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
// Parse provider names - they start with whitespace and are single words
const lines = text.trim().split('\n')
const providers = lines.filter(line => {
const trimmed = line.trim()
// Provider names are single words that start with whitespace in original line
return line.startsWith(' ') &&
trimmed.length > 0 &&
!trimmed.includes(' ') &&
!trimmed.includes(':') &&
!trimmed.includes('.')
}).map(line => line.trim())
availableProviders = providers
locationProviderAvailable = providers.length > 0
if (locationProviderAvailable && !currentProvider) {
currentProvider = providers[0]
}
// Providers detected
}
}
}
onExited: function(exitCode) {
if (exitCode !== 0) {
locationProviderAvailable = false
}
}
}
Process {
id: geoclueTestProcess
running: false
onExited: function(exitCode) {
if (exitCode === 0) {
const temperature = SessionData.nightModeTemperature || 4500
const dayTemp = 6500
gammaStepProcess.processType = "automation"
gammaStepProcess.command = buildGammastepCommand([
"-m", "wayland",
"-l", "geoclue2",
"-t", `${dayTemp}:${temperature}`,
"-v"
])
gammaStepProcess.running = true
} else {
SessionData.setNightModeAutoMode("time")
startTimeBasedMode()
}
}
}
Process {
id: gammaStepProcess
running: false
property string processType: "" // "automation", "activate", "reset", "test"
stdout: StdioCollector {
onStreamFinished: {}
}
stderr: StdioCollector {
onStreamFinished: {}
}
onRunningChanged: {
if (running) {
// Start timeout only for test commands - automation, activate, and reset should not timeout
if (processType === "test") {
processTimeoutTimer.start()
}
} else {
// Stop timeout when process ends
processTimeoutTimer.stop()
}
}
onExited: function(exitCode) {
processTimeoutTimer.stop()
const isSuccessfulCompletion = (exitCode === 0) ||
((processType === "activate" || processType === "reset") && exitCode === 15)
if (!isSuccessfulCompletion) {
switch(processType) {
case "automation":
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "location") {
if (exitCode === 15 || exitCode === 124) {
SessionData.setNightModeAutoMode("time")
startTimeBasedMode()
} else {
restartTimer.start()
}
} else if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "time") {
restartTimer.start()
}
break
}
}
}
}
Timer {
id: processTimeoutTimer
interval: 30000 // 30 second timeout (increased from 10s for one-shot commands)
running: false
repeat: false
onTriggered: {
if (gammaStepProcess.running) {
console.warn("NightModeAutomationService: Test process timed out, killing process")
// Only kill test processes that have timed out
if (gammaStepProcess.processType === "test") {
gammaStepProcess.running = false
} else {
console.warn("NightModeAutomationService: Non-test process still running after timeout, but not killing")
}
}
}
}
Timer {
id: restartTimer
interval: 10000
running: false
repeat: false
onTriggered: {
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "location") {
startLocationBasedMode()
}
}
}
Timer {
id: testFeedbackTimer
interval: 2000
running: false
repeat: false
property string feedbackMessage: ""
onTriggered: {
if (feedbackMessage.length > 0) {
console.log(feedbackMessage)
feedbackMessage = ""
}
}
}
Connections {
target: SessionData
function onNightModeAutoEnabledChanged() {
console.log("NightModeAutomationService: Auto enabled changed to", SessionData.nightModeAutoEnabled)
if (SessionData.nightModeAutoEnabled) {
startAutomation()
} else {
stopAutomation()
}
}
function onNightModeAutoModeChanged() {
if (SessionData.nightModeAutoEnabled) {
startAutomation()
}
}
function onNightModeStartTimeChanged() {
console.log("NightModeAutomationService: Start time changed to", SessionData.nightModeStartTime)
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "time") {
checkTimeBasedMode()
}
}
function onNightModeEndTimeChanged() {
console.log("NightModeAutomationService: End time changed to", SessionData.nightModeEndTime)
if (SessionData.nightModeAutoEnabled && SessionData.nightModeAutoMode === "time") {
checkTimeBasedMode()
}
}
function onNightModeTemperatureChanged() {
if (SessionData.nightModeAutoEnabled) {
startAutomation()
}
}
function onLatitudeChanged() {
updateFromSessionData()
}
function onLongitudeChanged() {
updateFromSessionData()
}
}
}