mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2025-12-06 06:36:15 +00:00
DarkModeService: Add settings and manual scheduling mode.
This commit is contained in:
@@ -354,6 +354,9 @@ Singleton {
|
||||
property bool useWallpaperColors: false
|
||||
property string predefinedScheme: "Noctalia (default)"
|
||||
property bool darkMode: true
|
||||
property string schedulingMode: "off"
|
||||
property string manualSunrise: "06:30"
|
||||
property string manualSunset: "18:30"
|
||||
property string matugenSchemeType: "scheme-fruit-salad"
|
||||
property bool generateTemplatesForPredefined: true
|
||||
}
|
||||
|
||||
@@ -13,6 +13,24 @@ ColumnLayout {
|
||||
property var schemeColorsCache: ({})
|
||||
property int cacheVersion: 0 // Increment to trigger UI updates
|
||||
|
||||
// Time dropdown options (00:00 .. 23:30)
|
||||
ListModel {
|
||||
id: timeOptions
|
||||
}
|
||||
Component.onCompleted: {
|
||||
for (var h = 0; h < 24; h++) {
|
||||
for (var m = 0; m < 60; m += 30) {
|
||||
var hh = ("0" + h).slice(-2)
|
||||
var mm = ("0" + m).slice(-2)
|
||||
var key = hh + ":" + mm
|
||||
timeOptions.append({
|
||||
"key": key,
|
||||
"name": key
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spacing: Style.marginL
|
||||
|
||||
// Helper function to extract scheme name from path
|
||||
@@ -148,6 +166,77 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
label: "Dark Mode Schedule"
|
||||
description: "Enables automatic switching between light and dark mode"
|
||||
|
||||
model: [{
|
||||
"name": "Off",
|
||||
"key": "off"
|
||||
}, {
|
||||
"name": "Manual",
|
||||
"key": "manual"
|
||||
}, {
|
||||
"name": "Sunrise/Sunset",
|
||||
"key": "location"
|
||||
}]
|
||||
|
||||
currentKey: Settings.data.colorSchemes.schedulingMode
|
||||
|
||||
onSelected: key => {
|
||||
Settings.data.colorSchemes.schedulingMode = key
|
||||
AppThemeService.generate()
|
||||
}
|
||||
}
|
||||
|
||||
// Manual scheduling
|
||||
ColumnLayout {
|
||||
spacing: Style.marginS
|
||||
visible: Settings.data.colorSchemes.schedulingMode === "manual"
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("settings.display.night-light.manual-schedule.label")
|
||||
description: I18n.tr("settings.display.night-light.manual-schedule.description")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: false
|
||||
spacing: Style.marginS
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.manual-schedule.sunrise")
|
||||
pointSize: Style.fontSizeM
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
model: timeOptions
|
||||
currentKey: Settings.data.colorSchemes.manualSunrise
|
||||
placeholder: I18n.tr("settings.display.night-light.manual-schedule.select-start")
|
||||
onSelected: key => Settings.data.colorSchemes.manualSunrise = key
|
||||
minimumWidth: 120
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: 20
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.manual-schedule.sunset")
|
||||
pointSize: Style.fontSizeM
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
model: timeOptions
|
||||
currentKey: Settings.data.colorSchemes.manualSunset
|
||||
placeholder: I18n.tr("settings.display.night-light.manual-schedule.select-stop")
|
||||
onSelected: key => Settings.data.colorSchemes.manualSunset = key
|
||||
minimumWidth: 120
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use Wallpaper Colors
|
||||
NToggle {
|
||||
label: I18n.tr("settings.color-scheme.color-source.use-wallpaper-colors.label")
|
||||
|
||||
@@ -13,31 +13,118 @@ Singleton {
|
||||
|
||||
Connections {
|
||||
target: LocationService.data
|
||||
enabled: Settings.data.colorSchemes.schedulingMode == "location"
|
||||
function onWeatherChanged() {
|
||||
if (LocationService.data.weather !== null) {
|
||||
const changes = root.collectChanges(LocationService.data.weather)
|
||||
const changes = root.collectWeatherChanges(LocationService.data.weather)
|
||||
if (!root.initComplete) {
|
||||
root.initComplete = true
|
||||
root.resetDarkMode(changes)
|
||||
root.applyCurrentMode(changes)
|
||||
}
|
||||
root.scheduleChange(changes)
|
||||
root.scheduleNextMode(changes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Settings.data.colorSchemes
|
||||
enabled: Settings.data.colorSchemes.schedulingMode == "manual"
|
||||
function onManualSunriseChanged() {
|
||||
const changes = root.collectManualChanges()
|
||||
root.applyCurrentMode(changes)
|
||||
root.scheduleNextMode(changes)
|
||||
}
|
||||
function onManualSunsetChanged() {
|
||||
const changes = root.collectManualChanges()
|
||||
root.applyCurrentMode(changes)
|
||||
root.scheduleNextMode(changes)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Settings.data.colorSchemes
|
||||
function onSchedulingModeChanged() {
|
||||
root.init()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
onTriggered: {
|
||||
Settings.data.colorSchemes.darkMode = root.nextDarkModeState
|
||||
if (LocationService.data.weather !== null) {
|
||||
const changes = root.collectChanges(LocationService.data.weather)
|
||||
root.scheduleChange(changes)
|
||||
const changes = root.collectWeatherChanges(LocationService.data.weather)
|
||||
root.scheduleNextMode(changes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function collectChanges(weather) {
|
||||
function init() {
|
||||
Logger.log("DarkModeService", "Service started")
|
||||
|
||||
if (Settings.data.colorSchemes.schedulingMode == "manual") {
|
||||
const changes = collectManualChanges()
|
||||
initComplete = true
|
||||
applyCurrentMode(changes)
|
||||
scheduleNextMode(changes)
|
||||
}
|
||||
|
||||
if (Settings.data.colorSchemes.schedulingMode == "location" && LocationService.data.weather) {
|
||||
const changes = collectWeatherChanges(LocationService.data.weather)
|
||||
initComplete = true
|
||||
applyCurrentMode(changes)
|
||||
scheduleNextMode(changes)
|
||||
}
|
||||
}
|
||||
|
||||
function parseTime(timeString) {
|
||||
const parts = timeString.split(":").map(Number)
|
||||
return {
|
||||
"hour": parts[0],
|
||||
"minute": parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
function collectManualChanges() {
|
||||
const sunriseTime = parseTime(Settings.data.colorSchemes.manualSunrise)
|
||||
const sunsetTime = parseTime(Settings.data.colorSchemes.manualSunset)
|
||||
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = now.getMonth()
|
||||
const day = now.getDate()
|
||||
|
||||
const yesterdaysSunset = new Date(year, month, day - 1, sunsetTime.hour, sunsetTime.minute)
|
||||
const todaysSunrise = new Date(year, month, day, sunriseTime.hour, sunriseTime.minute)
|
||||
const todaysSunset = new Date(year, month, day, sunsetTime.hour, sunsetTime.minute)
|
||||
const tomorrowsSunrise = new Date(year, month, day + 1, sunriseTime.hour, sunriseTime.minute)
|
||||
|
||||
return [{
|
||||
"time": yesterdaysSunset.getTime(),
|
||||
"darkMode": true
|
||||
}, {
|
||||
"time": todaysSunrise.getTime(),
|
||||
"darkMode": false
|
||||
}, {
|
||||
"time": todaysSunset.getTime(),
|
||||
"darkMode": true
|
||||
}, {
|
||||
"time": tomorrowsSunrise.getTime(),
|
||||
"darkMode": false
|
||||
}]
|
||||
}
|
||||
|
||||
function collectWeatherChanges(weather) {
|
||||
const changes = []
|
||||
|
||||
if (Date.now() < Date.parse(weather.daily.sunrise[0])) {
|
||||
// The sun has not risen yet
|
||||
changes.push({
|
||||
"time": Date.now() - 1,
|
||||
"darkMode": true
|
||||
})
|
||||
}
|
||||
|
||||
for (var i = 0; i < weather.daily.sunrise.length; i++) {
|
||||
changes.push({
|
||||
"time": Date.parse(weather.daily.sunrise[i]),
|
||||
@@ -48,10 +135,11 @@ Singleton {
|
||||
"darkMode": true
|
||||
})
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
function resetDarkMode(changes) {
|
||||
function applyCurrentMode(changes) {
|
||||
const now = Date.now()
|
||||
|
||||
// changes.findLast(change => change.time < now) // not available in QML...
|
||||
@@ -68,7 +156,7 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleChange(changes) {
|
||||
function scheduleNextMode(changes) {
|
||||
const now = Date.now()
|
||||
const nextChange = changes.find(change => change.time > now)
|
||||
if (nextChange) {
|
||||
@@ -78,8 +166,4 @@ Singleton {
|
||||
Logger.log("DarkModeService", `Scheduled: darkmode=${nextChange.darkMode} in ${timer.interval} ms`)
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
Logger.log("DarkModeService", "Service started")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ Singleton {
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: 20 * 1000
|
||||
running: Settings.data.location.weatherEnabled
|
||||
running: Settings.data.location.weatherEnabled || Settings.data.colorSchemes.schedulingMode == "location"
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
updateWeather()
|
||||
|
||||
Reference in New Issue
Block a user