fix(nightlight): make weather location a real mode and clarify the UI

This commit is contained in:
Lemmy
2026-05-10 18:11:53 -04:00
parent 599fcd6636
commit f0e459cc73
6 changed files with 79 additions and 40 deletions
+5 -5
View File
@@ -1585,23 +1585,23 @@
},
"use-weather-location": {
"label": "Use Weather Location",
"description": "Use weather service location for sunrise/sunset"
"description": "Use weather service location for sunrise/sunset instead of a manual schedule"
},
"night-light-start-time": {
"label": "Start Time",
"description": "Night light start time in HH:MM"
"description": "Manual night light start time in HH:MM when weather location is off"
},
"night-light-stop-time": {
"label": "Stop Time",
"description": "Night light stop time in HH:MM"
"description": "Manual night light stop time in HH:MM when weather location is off"
},
"latitude": {
"label": "Latitude",
"description": "Manual sunrise/sunset latitude when fixed times are unset"
"description": "Manual sunrise/sunset latitude when weather location is off and fixed times are unset"
},
"longitude": {
"label": "Longitude",
"description": "Manual sunrise/sunset longitude when fixed times are unset"
"description": "Manual sunrise/sunset longitude when weather location is off and fixed times are unset"
},
"day-temperature": {
"label": "Day Temperature",
+3 -3
View File
@@ -142,12 +142,12 @@ enable_ddcutil = false
[nightlight]
enabled = false
force = false
use_weather_location = true
use_weather_location = true # use weather coordinates instead of manual schedule/location
temperature_day = 6500 # Kelvin
temperature_night = 4000 # Kelvin
# start_time = "20:30" # HH:MM — explicit schedule takes priority over geolocation
# start_time = "20:30" # HH:MM — used when use_weather_location = false
# stop_time = "07:30"
# latitude = 52.5200
# latitude = 52.5200 # fallback when use_weather_location = false and start/stop are unset
# longitude = 13.4050
# ── Idle ──────────────────────────────────────────────────────────────────────
+2 -2
View File
@@ -497,8 +497,8 @@ struct NightLightConfig {
bool enabled = false;
bool force = false;
bool useWeatherLocation = true; // use WeatherService coordinates when start/stop and explicit lat/long are not set
std::string startTime; // HH:MM sunset (night start), overrides location mode when paired with stop_time
bool useWeatherLocation = true; // use WeatherService coordinates instead of manual schedule/location
std::string startTime; // HH:MM sunset (night start), used when use_weather_location is false
std::string stopTime; // HH:MM sunrise (day start)
std::optional<double> latitude;
std::optional<double> longitude;
+33 -16
View File
@@ -693,22 +693,39 @@ namespace settings {
tr("settings.schema.services.use-weather-location.description"),
{"nightlight", "use_weather_location"},
ToggleSetting{cfg.nightlight.useWeatherLocation}, "location"));
entries.push_back(
makeEntry("services", "night-light", tr("settings.schema.services.night-light-start-time.label"),
tr("settings.schema.services.night-light-start-time.description"), {"nightlight", "start_time"},
TextSetting{cfg.nightlight.startTime, "20:30"}, "time schedule sunset"));
entries.push_back(makeEntry("services", "night-light", tr("settings.schema.services.night-light-stop-time.label"),
tr("settings.schema.services.night-light-stop-time.description"),
{"nightlight", "stop_time"}, TextSetting{cfg.nightlight.stopTime, "07:30"},
"time schedule sunrise"));
entries.push_back(makeEntry("services", "night-light", tr("settings.schema.services.latitude.label"),
tr("settings.schema.services.latitude.description"), {"nightlight", "latitude"},
OptionalNumberSetting{cfg.nightlight.latitude, -90.0, 90.0, "52.5200"},
"coordinate location sunrise sunset", true));
entries.push_back(makeEntry("services", "night-light", tr("settings.schema.services.longitude.label"),
tr("settings.schema.services.longitude.description"), {"nightlight", "longitude"},
OptionalNumberSetting{cfg.nightlight.longitude, -180.0, 180.0, "13.4050"},
"coordinate location sunrise sunset", true));
const SettingVisibility weatherLocationOff{{"nightlight", "use_weather_location"}, {"false"}};
{
auto e =
makeEntry("services", "night-light", tr("settings.schema.services.night-light-start-time.label"),
tr("settings.schema.services.night-light-start-time.description"), {"nightlight", "start_time"},
TextSetting{cfg.nightlight.startTime, "20:30"}, "time schedule sunset");
e.visibleWhen = weatherLocationOff;
entries.push_back(std::move(e));
}
{
auto e =
makeEntry("services", "night-light", tr("settings.schema.services.night-light-stop-time.label"),
tr("settings.schema.services.night-light-stop-time.description"), {"nightlight", "stop_time"},
TextSetting{cfg.nightlight.stopTime, "07:30"}, "time schedule sunrise");
e.visibleWhen = weatherLocationOff;
entries.push_back(std::move(e));
}
{
auto e = makeEntry("services", "night-light", tr("settings.schema.services.latitude.label"),
tr("settings.schema.services.latitude.description"), {"nightlight", "latitude"},
OptionalNumberSetting{cfg.nightlight.latitude, -90.0, 90.0, "52.5200"},
"coordinate location sunrise sunset", true);
e.visibleWhen = weatherLocationOff;
entries.push_back(std::move(e));
}
{
auto e = makeEntry("services", "night-light", tr("settings.schema.services.longitude.label"),
tr("settings.schema.services.longitude.description"), {"nightlight", "longitude"},
OptionalNumberSetting{cfg.nightlight.longitude, -180.0, 180.0, "13.4050"},
"coordinate location sunrise sunset", true);
e.visibleWhen = weatherLocationOff;
entries.push_back(std::move(e));
}
// Both sliders span the same range; the day > night invariant is enforced at commit time
// via SliderSetting::linkedCommit, which pushes the other temperature when needed.
const float tempMin = static_cast<float>(NightLightConfig::kTemperatureMin);
+29 -14
View File
@@ -122,8 +122,23 @@ bool GammaService::effectiveForce() const {
return m_config.force;
}
GammaService::GeoCoordinates GammaService::scheduleCoordinates() const {
if (m_config.useWeatherLocation) {
return GeoCoordinates{.latitude = m_weatherLatitude, .longitude = m_weatherLongitude};
}
if (m_config.latitude.has_value() || m_config.longitude.has_value()) {
if (m_config.latitude.has_value() && m_config.longitude.has_value()) {
return GeoCoordinates{.latitude = m_config.latitude, .longitude = m_config.longitude};
}
return GeoCoordinates{};
}
return GeoCoordinates{};
}
bool GammaService::isManualMode() const {
return !effectiveForce() && normalizedClock(m_config.startTime).has_value() &&
return !effectiveForce() && !m_config.useWeatherLocation && normalizedClock(m_config.startTime).has_value() &&
normalizedClock(m_config.stopTime).has_value();
}
@@ -256,13 +271,12 @@ GammaService::SolarTimes GammaService::computeSolarTimes(double lat, double lon)
}
bool GammaService::isGeoNightPhase() const {
const auto lat = m_config.latitude.has_value() ? m_config.latitude : m_weatherLatitude;
const auto lon = m_config.longitude.has_value() ? m_config.longitude : m_weatherLongitude;
if (!lat.has_value() || !lon.has_value()) {
const auto coords = scheduleCoordinates();
if (!coords.latitude.has_value() || !coords.longitude.has_value()) {
return false;
}
const auto times = computeSolarTimes(*lat, *lon);
const auto times = computeSolarTimes(*coords.latitude, *coords.longitude);
if (times.sunriseMinutes == 0 && times.sunsetMinutes == 0) {
return true;
}
@@ -285,13 +299,12 @@ bool GammaService::isGeoNightPhase() const {
}
std::chrono::milliseconds GammaService::msUntilNextGeoBoundary() const {
const auto lat = m_config.latitude.has_value() ? m_config.latitude : m_weatherLatitude;
const auto lon = m_config.longitude.has_value() ? m_config.longitude : m_weatherLongitude;
if (!lat.has_value() || !lon.has_value()) {
const auto coords = scheduleCoordinates();
if (!coords.latitude.has_value() || !coords.longitude.has_value()) {
return std::chrono::milliseconds(3600000);
}
const auto times = computeSolarTimes(*lat, *lon);
const auto times = computeSolarTimes(*coords.latitude, *coords.longitude);
if (times.sunriseMinutes == 0 && (times.sunsetMinutes == 0 || times.sunsetMinutes == 1440)) {
return std::chrono::milliseconds(3600000);
}
@@ -565,13 +578,15 @@ int GammaService::targetTemperature() const {
}
// Geo mode — need coordinates.
const auto lat = m_config.latitude.has_value() ? m_config.latitude : m_weatherLatitude;
const auto lon = m_config.longitude.has_value() ? m_config.longitude : m_weatherLongitude;
if (!lat.has_value() || !lon.has_value()) {
if (m_config.latitude.has_value() || m_config.longitude.has_value()) {
const auto coords = scheduleCoordinates();
if (!coords.latitude.has_value() || !coords.longitude.has_value()) {
if (!m_config.useWeatherLocation && (m_config.latitude.has_value() || m_config.longitude.has_value())) {
kLog.warn("need both latitude and longitude when overriding location mode");
} else if (!m_config.useWeatherLocation) {
kLog.warn("no schedule: set start_time/stop_time or latitude/longitude, or enable weather location");
} else {
kLog.warn("no schedule: set start_time/stop_time or latitude/longitude, or enable weather");
kLog.warn("no schedule: set start_time/stop_time, disable weather location and set latitude/longitude, or enable "
"weather");
}
return -1;
}
+7
View File
@@ -49,6 +49,13 @@ private:
[[nodiscard]] bool effectiveConfiguredEnabled() const;
[[nodiscard]] bool effectiveEnabled() const;
[[nodiscard]] bool effectiveForce() const;
struct GeoCoordinates {
std::optional<double> latitude;
std::optional<double> longitude;
};
[[nodiscard]] GeoCoordinates scheduleCoordinates() const;
[[nodiscard]] bool isManualMode() const;
[[nodiscard]] bool isManualNightPhase() const;
[[nodiscard]] std::chrono::milliseconds msUntilNextManualBoundary() const;