1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

gamma: display automation state in UI

This commit is contained in:
bbedward
2025-12-09 11:26:28 -05:00
parent da4561cb35
commit f88f1ea951
7 changed files with 279 additions and 68 deletions

View File

@@ -255,7 +255,6 @@ Singleton {
property int batterySuspendBehavior: SettingsData.SuspendBehavior.Suspend
property string batteryProfileName: ""
property bool lockBeforeSuspend: false
property bool preventIdleForMedia: false
property bool loginctlLockIntegration: true
property bool fadeToLockEnabled: false
property int fadeToLockGracePeriod: 5

View File

@@ -154,7 +154,6 @@ var SPEC = {
batterySuspendBehavior: { def: 0 },
batteryProfileName: { def: "" },
lockBeforeSuspend: { def: false },
preventIdleForMedia: { def: false },
loginctlLockIntegration: { def: true },
fadeToLockEnabled: { def: false },
fadeToLockGracePeriod: { def: 5 },

View File

@@ -8,6 +8,19 @@ import qs.Widgets
Item {
id: displaysTab
function formatGammaTime(isoString) {
if (!isoString)
return "";
try {
const date = new Date(isoString);
if (isNaN(date.getTime()))
return "";
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
} catch (e) {
return "";
}
}
function getBarComponentsFromSettings() {
const bars = SettingsData.barConfigs || [];
return bars.map(bar => ({
@@ -530,6 +543,233 @@ Item {
}
}
}
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.2
visible: gammaStatusSection.visible
}
Column {
id: gammaStatusSection
width: parent.width
spacing: Theme.spacingM
visible: DisplayService.nightModeEnabled && DisplayService.gammaCurrentTemp > 0
Row {
width: parent.width
spacing: Theme.spacingS
DankIcon {
name: DisplayService.gammaIsDay ? "light_mode" : "dark_mode"
size: Theme.iconSizeSmall
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Current Status")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
width: parent.width
spacing: Theme.spacingM
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: tempColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
Column {
id: tempColumn
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "device_thermostat"
size: Theme.iconSize
color: Theme.primary
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: DisplayService.gammaCurrentTemp + "K"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("Current Temp")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: periodColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
Column {
id: periodColumn
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: DisplayService.gammaIsDay ? "wb_sunny" : "nightlight"
size: Theme.iconSize
color: DisplayService.gammaIsDay ? "#FFA726" : "#7E57C2"
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: DisplayService.gammaIsDay ? I18n.tr("Daytime") : I18n.tr("Night")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("Current Period")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Row {
width: parent.width
spacing: Theme.spacingM
visible: SessionData.nightModeAutoMode === "location" && (DisplayService.gammaSunriseTime || DisplayService.gammaSunsetTime)
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: sunriseColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
visible: DisplayService.gammaSunriseTime
Column {
id: sunriseColumn
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "wb_twilight"
size: Theme.iconSize
color: "#FF7043"
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: displaysTab.formatGammaTime(DisplayService.gammaSunriseTime)
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("Sunrise")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Rectangle {
width: (parent.width - Theme.spacingM) / 2
height: sunsetColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
visible: DisplayService.gammaSunsetTime
Column {
id: sunsetColumn
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "wb_twilight"
size: Theme.iconSize
color: "#5C6BC0"
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: displaysTab.formatGammaTime(DisplayService.gammaSunsetTime)
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: I18n.tr("Sunset")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Rectangle {
width: parent.width
height: nextChangeRow.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
visible: DisplayService.gammaNextTransition
Row {
id: nextChangeRow
anchors.centerIn: parent
spacing: Theme.spacingM
DankIcon {
name: "schedule"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: 2
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: I18n.tr("Next Transition")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
StyledText {
text: displaysTab.formatGammaTime(DisplayService.gammaNextTransition)
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
}
}
}
}
}
}
}
}

View File

@@ -61,14 +61,6 @@ Item {
}
}
SettingsToggleRow {
text: I18n.tr("Prevent idle for media")
description: I18n.tr("Inhibit idle timeout when audio or video is playing")
checked: SettingsData.preventIdleForMedia
visible: IdleService.idleMonitorAvailable
onToggled: checked => SettingsData.set("preventIdleForMedia", checked)
}
SettingsToggleRow {
text: I18n.tr("Fade to lock screen")
description: I18n.tr("Gradually fade the screen before locking with a configurable grace period")
@@ -76,6 +68,14 @@ Item {
onToggled: checked => SettingsData.set("fadeToLockEnabled", checked)
}
SettingsToggleRow {
text: I18n.tr("Lock before suspend")
description: I18n.tr("Automatically lock the screen when the system prepares to suspend")
checked: SettingsData.lockBeforeSuspend
visible: SessionService.loginctlAvailable && SettingsData.loginctlLockIntegration
onToggled: checked => SettingsData.set("lockBeforeSuspend", checked)
}
SettingsDropdownRow {
id: fadeGracePeriodDropdown
property var periodOptions: ["1 second", "2 seconds", "3 seconds", "4 seconds", "5 seconds", "10 seconds", "15 seconds", "20 seconds", "30 seconds"]
@@ -114,14 +114,14 @@ Item {
function onCurrentIndexChanged() {
const currentProfile = powerCategory.currentIndex === 0 ? SettingsData.acProfileName : SettingsData.batteryProfileName;
const index = powerProfileDropdown.profileValues.indexOf(currentProfile);
powerProfileDropdown.currentValue = powerProfileDropdown.profileOptions[index]
powerProfileDropdown.currentValue = powerProfileDropdown.profileOptions[index];
}
}
Component.onCompleted: {
const currentProfile = powerCategory.currentIndex === 0 ? SettingsData.acProfileName : SettingsData.batteryProfileName;
const index = profileValues.indexOf(currentProfile);
currentValue = profileOptions[index]
currentValue = profileOptions[index];
}
onValueChanged: value => {

View File

@@ -49,6 +49,7 @@ Singleton {
signal extWorkspaceStateUpdate(var data)
signal wlrOutputStateUpdate(var data)
signal evdevStateUpdate(var data)
signal gammaStateUpdate(var data)
signal openUrlRequested(string url)
signal appPickerRequested(var data)
@@ -267,9 +268,9 @@ Singleton {
function removeSubscription(service) {
if (activeSubscriptions.includes("all")) {
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "dwl", "brightness", "extworkspace", "browser"]
const filtered = allServices.filter(s => s !== service)
subscribe(filtered)
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "dwl", "brightness", "extworkspace", "browser"];
const filtered = allServices.filter(s => s !== service);
subscribe(filtered);
} else {
const filtered = activeSubscriptions.filter(s => s !== service);
if (filtered.length === 0) {
@@ -289,9 +290,9 @@ Singleton {
excludeServices = [excludeServices];
}
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser"]
const filtered = allServices.filter(s => !excludeServices.includes(s))
subscribe(filtered)
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser"];
const filtered = allServices.filter(s => !excludeServices.includes(s));
subscribe(filtered);
}
function handleSubscriptionEvent(response) {
@@ -355,16 +356,18 @@ Singleton {
if (data.capsLock !== undefined) {
capsLockState = data.capsLock;
}
evdevStateUpdate(data)
evdevStateUpdate(data);
} else if (service === "gamma") {
gammaStateUpdate(data);
} else if (service === "browser.open_requested") {
if (data.target) {
if (data.requestType === "url" || !data.requestType) {
openUrlRequested(data.target)
openUrlRequested(data.target);
} else {
appPickerRequested(data)
appPickerRequested(data);
}
} else if (data.url) {
openUrlRequested(data.url)
openUrlRequested(data.url);
}
}
}

View File

@@ -41,6 +41,18 @@ Singleton {
property bool automationAvailable: false
property bool gammaControlAvailable: false
property var gammaState: ({})
property int gammaCurrentTemp: gammaState?.currentTemp ?? 0
property string gammaNextTransition: gammaState?.nextTransition ?? ""
property string gammaSunriseTime: gammaState?.sunriseTime ?? ""
property string gammaSunsetTime: gammaState?.sunsetTime ?? ""
property string gammaDawnTime: gammaState?.dawnTime ?? ""
property string gammaNightTime: gammaState?.nightTime ?? ""
property bool gammaIsDay: gammaState?.isDay ?? true
property real gammaSunPosition: gammaState?.sunPosition ?? 0
property int gammaLowTemp: gammaState?.config?.LowTemp ?? 0
property int gammaHighTemp: gammaState?.config?.HighTemp ?? 0
function markDeviceUserControlled(deviceId) {
const newControlled = Object.assign({}, userControlledDevices);
newControlled[deviceId] = Date.now();
@@ -809,6 +821,10 @@ Singleton {
osdSuppressTimer.restart();
}
}
function onGammaStateUpdate(data) {
root.gammaState = data;
}
}
// Session Data Connections

View File

@@ -58,43 +58,12 @@ Singleton {
property var monitorOffMonitor: null
property var lockMonitor: null
property var suspendMonitor: null
property var mediaInhibitor: null
property var lockComponent: null
function wake() {
requestMonitorOn();
}
function createMediaInhibitor() {
if (!idleInhibitorAvailable) {
return;
}
if (mediaInhibitor) {
mediaInhibitor.destroy();
mediaInhibitor = null;
}
const inhibitorString = `
import QtQuick
import Quickshell.Wayland
IdleInhibitor {
active: false
}
`;
mediaInhibitor = Qt.createQmlObject(inhibitorString, root, "IdleService.MediaInhibitor");
mediaInhibitor.active = Qt.binding(() => root.mediaPlaying);
}
function destroyMediaInhibitor() {
if (mediaInhibitor) {
mediaInhibitor.destroy();
mediaInhibitor = null;
}
}
function createIdleMonitors() {
if (!idleMonitorAvailable) {
console.info("IdleService: IdleMonitor not available, skipping creation");
@@ -152,10 +121,6 @@ Singleton {
root.requestSuspend();
}
});
if (SettingsData.preventIdleForMedia) {
createMediaInhibitor();
}
} catch (e) {
console.warn("IdleService: Error creating IdleMonitors:", e);
}
@@ -176,17 +141,6 @@ Singleton {
}
}
Connections {
target: SettingsData
function onPreventIdleForMediaChanged() {
if (SettingsData.preventIdleForMedia) {
createMediaInhibitor();
} else {
destroyMediaInhibitor();
}
}
}
Component.onCompleted: {
if (!idleMonitorAvailable) {
console.warn("IdleService: IdleMonitor not available - power management disabled. This requires a newer version of Quickshell.");