diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 03d657a..a8f7163 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -261,7 +261,6 @@ Singleton { // night light property JsonObject nightLight: JsonObject { property bool enabled: false - property real warmth: 0.0 property real intensity: 0.8 property string startTime: "20:00" property string stopTime: "07:00" diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index edea949..845e85f 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -15,33 +15,24 @@ Item { implicitHeight: pill.height visible: true - function getIcon() { - if (!NightLightService.enabled) { - return "light_mode" - } - return NightLightService.isActive ? "dark_mode" : "light_mode" - } - - function getTooltipText() { - if (!NightLightService.enabled) { - return "Night Light: Disabled\nLeft click to open settings.\nRight click to enable." - } - - var status = NightLightService.isActive ? "Active" : "Inactive (outside schedule)" - var warmth = Math.round(NightLightService.warmth * 10) - var schedule = NightLightService.autoSchedule ? `Schedule: ${NightLightService.startTime} - ${NightLightService.stopTime}` : "Manual mode" - - return `Night Light: ${status}\nWarmth: ${warmth}/10\n${schedule}\nLeft click to open settings.\nRight click to toggle.` - } - NPill { id: pill - icon: getIcon() + icon: NightLightService.isActive ? "bedtime" : "bedtime_off" iconCircleColor: NightLightService.isActive ? Color.mSecondary : Color.mOnSurfaceVariant collapsedIconColor: NightLightService.isActive ? Color.mOnSecondary : Color.mOnSurface autoHide: false - text: NightLightService.enabled ? (NightLightService.isActive ? "ON" : "OFF") : "OFF" - tooltipText: getTooltipText() + text: NightLightService.isActive ? "On" : "Off" + tooltipText: { + if (!Settings.isLoaded || !Settings.data.nightLight.enabled) { + return "Night Light: Disabled\nLeft click to open settings.\nRight click to enable." + } + + var status = NightLightService.isActive ? "Active" : "Inactive (outside schedule)" + var intensity = Math.round(Settings.data.nightLight.intensity * 100) + var schedule = Settings.data.nightLight.autoSchedule ? `Schedule: ${Settings.data.nightLight.startTime} - ${Settings.data.nightLight.stopTime}` : "Manual mode" + + return `Intensity: ${intensity}%\n${schedule}\nLeft click to open settings.\nRight click to toggle.` + } onClicked: { // Left click - open settings @@ -52,34 +43,13 @@ Item { onRightClicked: { // Right click - toggle night light - NightLightService.toggle() + Settings.data.nightLight.enabled = !Settings.data.nightLight.enabled } - } - // Update when service state changes - Connections { - target: NightLightService - function onEnabledChanged() { - pill.icon = getIcon() - pill.text = NightLightService.enabled ? (NightLightService.isActive ? "ON" : "OFF") : "OFF" - pill.tooltipText = getTooltipText() - } - function onIsActiveChanged() { - pill.icon = getIcon() - pill.text = NightLightService.enabled ? (NightLightService.isActive ? "ON" : "OFF") : "OFF" - pill.tooltipText = getTooltipText() - } - function onWarmthChanged() { - pill.tooltipText = getTooltipText() - } - function onStartTimeChanged() { - pill.tooltipText = getTooltipText() - } - function onStopTimeChanged() { - pill.tooltipText = getTooltipText() - } - function onAutoScheduleChanged() { - pill.tooltipText = getTooltipText() - } + onWheel: delta => { + var diff = delta > 0 ? 0.05 : -0.05 + Settings.data.nightLight.intensity = Math.max(0, Math.min(1.0, + Settings.data.nightLight.intensity + diff)) + } } } diff --git a/Modules/NightLight/NightLight.qml b/Modules/NightLight/NightLightOverlay.qml similarity index 52% rename from Modules/NightLight/NightLight.qml rename to Modules/NightLight/NightLightOverlay.qml index e6557cf..8bb74bc 100644 --- a/Modules/NightLight/NightLight.qml +++ b/Modules/NightLight/NightLightOverlay.qml @@ -11,17 +11,11 @@ Variants { required property ShellScreen modelData readonly property real scaling: ScalingService.scale(modelData) - active: NightLightService.enabled + active: NightLightService.isActive sourceComponent: PanelWindow { - id: nightlightWindow - screen: modelData - visible: NightLightService.isActive color: Color.transparent - - mask: Region {} - anchors { top: true bottom: true @@ -29,6 +23,9 @@ Variants { right: true } + // Ensure a full click through + mask: Region {} + WlrLayershell.layer: WlrLayershell.Overlay WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.keyboardFocus: WlrKeyboardFocus.None @@ -37,29 +34,13 @@ Variants { Rectangle { anchors.fill: parent color: NightLightService.overlayColor - } - // Safe connection that checks if the window still exists - Connections { - target: NightLightService - function onIsActiveChanged() { - if (nightlightWindow && typeof nightlightWindow.visible !== 'undefined') { - nightlightWindow.visible = NightLightService.isActive + Behavior on color { + ColorAnimation { + duration: Style.animationSlow } } } - - // Cleanup when component is being destroyed - Component.onDestruction: { - Logger.log("NightLight", "PanelWindow being destroyed") - } - } - - // Safe state changes - onActiveChanged: { - if (!active) { - Logger.log("NightLight", "Loader deactivating for screen:", modelData.name) - } } } } diff --git a/Modules/SettingsPanel/Tabs/DisplayTab.qml b/Modules/SettingsPanel/Tabs/DisplayTab.qml index 16c3dd4..ff780aa 100644 --- a/Modules/SettingsPanel/Tabs/DisplayTab.qml +++ b/Modules/SettingsPanel/Tabs/DisplayTab.qml @@ -249,7 +249,7 @@ Item { NToggle { label: "Enable Night Light" description: "Apply a warm color filter to reduce blue light emission." - checked: NightLightService.enabled + checked: Settings.data.nightLight.enabled onToggled: checked => { Settings.data.nightLight.enabled = checked } @@ -258,62 +258,50 @@ Item { NToggle { label: "Auto Schedule" description: "Automatically enable night light based on time schedule." - checked: NightLightService.autoSchedule - enabled: NightLightService.enabled - onToggled: checked => { - NightLightService.setAutoSchedule(checked) - } + checked: Settings.data.nightLight.autoSchedule + enabled: Settings.data.nightLight.enabled + onToggled: checked => Settings.data.nightLight.autoSchedule = checked } - // Warmth settings - NText { - text: "Warmth" - font.pointSize: Style.fontSizeM * scaling - font.weight: Style.fontWeightBold - color: Color.mOnSurface - enabled: NightLightService.enabled - } + // Intensity settings + ColumnLayout { + spacing: Style.marginXS * scaling - NText { - text: "Higher values create warmer (more orange) light, lower values create cooler (more blue) light." - font.pointSize: Style.fontSizeS * scaling - color: Color.mOnSurfaceVariant - wrapMode: Text.WordWrap - Layout.fillWidth: true - enabled: NightLightService.enabled + NText { + text: "Intensity" + font.pointSize: Style.fontSizeM * scaling + font.weight: Style.fontWeightBold + color: Color.mOnSurface + enabled: Settings.data.nightLight.enabled + } + + NText { + text: "Higher values create warmer (more orange) light, lower values create cooler (more blue) light." + font.pointSize: Style.fontSizeS * scaling + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + enabled: Settings.data.nightLight.enabled + } } RowLayout { spacing: Style.marginS * scaling Layout.fillWidth: true - enabled: NightLightService.enabled + enabled: Settings.data.nightLight.enabled NSlider { - id: warmthSlider from: 0 - to: 10 - stepSize: 1 - value: Math.round(NightLightService.warmth * 10) - onPressedChanged: { - if (!pressed) { - NightLightService.setWarmth(value / 10) - } - } + to: 1 + stepSize: 0.01 + value: Settings.data.nightLight.intensity + onMoved: Settings.data.nightLight.intensity = value Layout.fillWidth: true Layout.minimumWidth: 150 * scaling } - Connections { - target: NightLightService - function onWarmthChanged() { - if (!warmthSlider.pressed) { - warmthSlider.value = Math.round(NightLightService.warmth * 10) - } - } - } - NText { - text: `${warmthSlider.value}` + text: `${Math.round(Settings.data.nightLight.intensity * 100)}%` Layout.alignment: Qt.AlignVCenter Layout.minimumWidth: 60 * scaling horizontalAlignment: Text.AlignRight @@ -321,55 +309,55 @@ Item { } // Schedule settings - NText { - text: "Schedule" - font.pointSize: Style.fontSizeM * scaling - font.weight: Style.fontWeightBold - color: Color.mOnSurface - enabled: NightLightService.enabled - } + ColumnLayout { + spacing: Style.marginXS * scaling - RowLayout { - spacing: Style.marginL * scaling - Layout.fillWidth: true - enabled: NightLightService.enabled - - ColumnLayout { - spacing: Style.marginXXS * scaling - Layout.fillWidth: true - - NText { - text: "Start Time" - font.pointSize: Style.fontSizeS * scaling - color: Color.mOnSurfaceVariant - } - - NComboBox { - model: timeOptions - currentKey: NightLightService.startTime - placeholder: "Select time" - onSelected: function (key) { - NightLightService.setSchedule(key, NightLightService.stopTime) - } - } + NText { + text: "Schedule" + font.pointSize: Style.fontSizeM * scaling + font.weight: Style.fontWeightBold + color: Color.mOnSurface + enabled: Settings.data.nightLight.enabled } - ColumnLayout { - spacing: Style.marginXXS * scaling + RowLayout { + spacing: Style.marginL * scaling Layout.fillWidth: true + enabled: Settings.data.nightLight.enabled - NText { - text: "Stop Time" - font.pointSize: Style.fontSizeS * scaling - color: Color.mOnSurfaceVariant + ColumnLayout { + spacing: Style.marginXXS * scaling + Layout.fillWidth: true + + NText { + text: "Start Time" + font.pointSize: Style.fontSizeS * scaling + color: Color.mOnSurfaceVariant + } + + NComboBox { + model: timeOptions + currentKey: Settings.data.nightLight.startTime + placeholder: "Select start time" + onSelected: key => Settings.data.nightLight.startTime = key + } } - NComboBox { - model: timeOptions - currentKey: NightLightService.stopTime - placeholder: "Select time" - onSelected: function (key) { - NightLightService.setSchedule(NightLightService.startTime, key) + ColumnLayout { + spacing: Style.marginXXS * scaling + Layout.fillWidth: true + + NText { + text: "Stop Time" + font.pointSize: Style.fontSizeS * scaling + color: Color.mOnSurfaceVariant + } + + NComboBox { + model: timeOptions + currentKey: Settings.data.nightLight.stopTime + placeholder: "Select stop time" + onSelected: key => Settings.data.nightLight.stopTime = key } } } diff --git a/Services/NightLightService.qml b/Services/NightLightService.qml index 0c781fe..f94e409 100644 --- a/Services/NightLightService.qml +++ b/Services/NightLightService.qml @@ -9,78 +9,40 @@ Singleton { id: root // Night Light properties - directly bound to settings - property bool enabled: Settings.data.nightLight?.enabled || false - property real warmth: (Settings.data.nightLight - && Settings.data.nightLight.warmth !== undefined) ? Settings.data.nightLight.warmth : 0.6 - property real intensity: (Settings.data.nightLight - && Settings.data.nightLight.intensity !== undefined) ? Settings.data.nightLight.intensity : 0.8 - property string startTime: Settings.data.nightLight?.startTime || "20:00" - property string stopTime: Settings.data.nightLight?.stopTime || "07:00" - property bool autoSchedule: Settings.data.nightLight?.autoSchedule !== false + readonly property var params: Settings.data.nightLight // Computed properties - property color overlayColor: enabled ? calculateOverlayColor() : "transparent" - property bool isActive: enabled && (autoSchedule ? isWithinSchedule() : true) + readonly property color overlayColor: params.enabled ? calculateOverlayColor() : "transparent" + property bool isActive: params.enabled && (params.autoSchedule ? isWithinSchedule() : true) Component.onCompleted: { Logger.log("NightLight", "Service started") } - function toggle() { - Settings.data.nightLight.enabled = !Settings.data.nightLight.enabled - Logger.log("NightLight", "Toggled:", Settings.data.nightLight.enabled) - } - - function setWarmth(value) { - Settings.data.nightLight.warmth = Math.max(0.0, Math.min(1.0, value)) - Logger.log("NightLight", "Warmth set to:", Settings.data.nightLight.warmth) - } - - function setIntensity(value) { - Settings.data.nightLight.intensity = Math.max(0.0, Math.min(1.0, value)) - Logger.log("NightLight", "Intensity set to:", Settings.data.nightLight.intensity) - } - - function setSchedule(start, stop) { - Settings.data.nightLight.startTime = start - Settings.data.nightLight.stopTime = stop - Logger.log("NightLight", "Schedule set to:", Settings.data.nightLight.startTime, "-", - Settings.data.nightLight.stopTime) - } - - function setAutoSchedule(auto) { - Settings.data.nightLight.autoSchedule = auto - Logger.log("NightLight", "Auto schedule set to:", Settings.data.nightLight.autoSchedule, "enabled:", enabled, - "isActive:", isActive, "withinSchedule:", isWithinSchedule()) - } - function calculateOverlayColor() { - if (!isActive) + if (!isActive) { return "transparent" + } // More vibrant color formula - stronger effect at high warmth var red = 1.0 - var green = 0.85 - warmth * 0.4 // More green reduction for stronger effect - var blue = 0.5 - warmth * 0.45 // More blue reduction for warmer feel - var alpha = 0.1 + warmth * 0.25 // Higher alpha for more noticeable effect - - // Apply intensity - red = red * intensity - green = green * intensity - blue = blue * intensity + var green = 1.0 - (0.43 * params.intensity) + var blue = 1.0 - (0.84 * params.intensity) + var alpha = (params.intensity * 0.25) // Higher alpha for more noticeable effect return Qt.rgba(red, green, blue, alpha) } function isWithinSchedule() { - if (!autoSchedule) + if (!params.autoSchedule) { return true + } var now = new Date() var currentTime = now.getHours() * 60 + now.getMinutes() - var startParts = startTime.split(":") - var stopParts = stopTime.split(":") + var startParts = params.startTime.split(":") + var stopParts = params.stopTime.split(":") var startMinutes = parseInt(startParts[0]) * 60 + parseInt(startParts[1]) var stopMinutes = parseInt(stopParts[0]) * 60 + parseInt(stopParts[1]) @@ -95,14 +57,10 @@ Singleton { // Timer to check schedule changes Timer { interval: 60000 // Check every minute - running: true + running: params.enabled && params.autoSchedule repeat: true onTriggered: { - if (autoSchedule && enabled) { - // Force overlay update when schedule changes - Logger.log("NightLight", "Schedule check - enabled:", enabled, "autoSchedule:", autoSchedule, "isActive:", - isActive, "withinSchedule:", isWithinSchedule()) - } + isActive = isWithinSchedule() } } } diff --git a/shell.qml b/shell.qml index feaceff..c62e8a2 100644 --- a/shell.qml +++ b/shell.qml @@ -40,7 +40,6 @@ ShellRoot { ScreenCorners {} Bar {} Dock {} - NightLight {} Notification { id: notification @@ -52,6 +51,8 @@ ShellRoot { ToastOverlay {} + NightLightOverlay {} + IPCManager {} // ------------------------------