sidebar: night light dialog

This commit is contained in:
end-4
2025-10-22 22:16:58 +02:00
parent 6ed9c9869e
commit bb08c61b76
9 changed files with 244 additions and 47 deletions
@@ -7,6 +7,7 @@ import QtQuick.Controls
RippleButton {
id: root
property string buttonIcon
property alias iconSize: iconWidget.iconSize
Layout.fillWidth: true
implicitHeight: contentItem.implicitHeight + 8 * 2
@@ -17,6 +18,7 @@ RippleButton {
contentItem: RowLayout {
spacing: 10
OptionalMaterialSymbol {
id: iconWidget
icon: root.buttonIcon
opacity: root.enabled ? 1 : 0.4
iconSize: Appearance.font.pixelSize.larger
@@ -0,0 +1,43 @@
pragma ComponentBehavior: Bound
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Widgets
Column {
id: root
property alias text: sliderName.text
property alias from: sliderWidget.from
property alias to: sliderWidget.to
property alias value: sliderWidget.value
property alias tooltipContent: sliderWidget.tooltipContent
property alias stopIndicatorValues: sliderWidget.stopIndicatorValues
signal moved()
spacing: -2
ContentSubsectionLabel {
id: sliderName
visible: text?.length > 0
text: ""
anchors {
left: parent.left
right: parent.right
}
}
StyledSlider {
id: sliderWidget
anchors {
left: parent.left
right: parent.right
leftMargin: 4
rightMargin: leftMargin
}
configuration: StyledSlider.Configuration.S
onMoved: root.moved()
}
}
@@ -11,19 +11,22 @@ import Quickshell.Hyprland
import qs.modules.sidebarRight.quickToggles
import qs.modules.sidebarRight.quickToggles.classicStyle
import qs.modules.sidebarRight.wifiNetworks
import qs.modules.sidebarRight.bluetoothDevices
import qs.modules.sidebarRight.nightLight
import qs.modules.sidebarRight.volumeMixer
import qs.modules.sidebarRight.wifiNetworks
Item {
id: root
property int sidebarWidth: Appearance.sizes.sidebarWidth
property int sidebarPadding: 10
property string settingsQmlPath: Quickshell.shellPath("settings.qml")
property bool showWifiDialog: false
property bool showBluetoothDialog: false
property bool showAudioOutputDialog: false
property bool showAudioInputDialog: false
property bool showBluetoothDialog: false
property bool showNightLightDialog: false
property bool showWifiDialog: false
property bool editMode: false
Connections {
@@ -109,18 +112,20 @@ Item {
}
ToggleDialog {
id: wifiDialogLoader
shownPropertyString: "showWifiDialog"
dialog: WifiDialog {}
onShownChanged: {
if (!shown) return;
Network.enableWifi();
Network.rescanWifi();
shownPropertyString: "showAudioOutputDialog"
dialog: VolumeDialog {
isSink: true
}
}
ToggleDialog {
shownPropertyString: "showAudioInputDialog"
dialog: VolumeDialog {
isSink: false
}
}
ToggleDialog {
id: bluetoothDialogLoader
shownPropertyString: "showBluetoothDialog"
dialog: BluetoothDialog {}
onShownChanged: {
@@ -130,23 +135,21 @@ Item {
Bluetooth.defaultAdapter.enabled = true;
Bluetooth.defaultAdapter.discovering = true;
}
}
}
ToggleDialog {
id: audioOutputDialogLoader
shownPropertyString: "showAudioOutputDialog"
dialog: VolumeDialog {
isSink: true
}
shownPropertyString: "showNightLightDialog"
dialog: NightLightDialog {}
}
ToggleDialog {
id: audioInputDialogLoader
shownPropertyString: "showAudioInputDialog"
dialog: VolumeDialog {
isSink: false
shownPropertyString: "showWifiDialog"
dialog: WifiDialog {}
onShownChanged: {
if (!shown) return;
Network.enableWifi();
Network.rescanWifi();
}
}
@@ -186,18 +189,21 @@ Item {
active: Config.options.sidebar.quickToggles.style === styleName
Connections {
target: quickPanelImplLoader.item
function onOpenWifiDialog() {
root.showWifiDialog = true;
}
function onOpenBluetoothDialog() {
root.showBluetoothDialog = true;
}
function onOpenAudioOutputDialog() {
root.showAudioOutputDialog = true;
}
function onOpenAudioInputDialog() {
root.showAudioInputDialog = true;
}
function onOpenBluetoothDialog() {
root.showBluetoothDialog = true;
}
function onOpenNightLightDialog() {
root.showNightLightDialog = true;
}
function onOpenWifiDialog() {
root.showWifiDialog = true;
}
}
}
@@ -0,0 +1,125 @@
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
WindowDialog {
id: root
property var screen: root.QsWindow.window?.screen
property var brightnessMonitor: Brightness.getMonitorForScreen(screen)
WindowDialogTitle {
text: Translation.tr("Eye protection")
}
WindowDialogSectionHeader {
text: Translation.tr("Night Light")
}
WindowDialogSeparator {
Layout.topMargin: -22
Layout.leftMargin: 0
Layout.rightMargin: 0
}
Column {
id: nightLightColumn
Layout.topMargin: -16
Layout.fillWidth: true
Layout.fillHeight: true
ConfigSwitch {
anchors {
left: parent.left
right: parent.right
}
iconSize: Appearance.font.pixelSize.larger
buttonIcon: "lightbulb"
text: Translation.tr("Enable now")
checked: Hyprsunset.active
onCheckedChanged: {
Hyprsunset.toggle(checked)
}
}
ConfigSwitch {
anchors {
left: parent.left
right: parent.right
}
iconSize: Appearance.font.pixelSize.larger
buttonIcon: "night_sight_auto"
text: Translation.tr("Automatic")
checked: Config.options.light.night.automatic
onCheckedChanged: {
Config.options.light.night.automatic = checked;
}
}
WindowDialogSlider {
anchors {
left: parent.left
right: parent.right
leftMargin: 4
rightMargin: 4
}
text: Translation.tr("Color temperature")
from: 1000
to: 20000
stopIndicatorValues: [6000, to]
value: Config.options.light.night.colorTemperature
onMoved: Config.options.light.night.colorTemperature = value
tooltipContent: `${Math.round(value)}K`
}
}
WindowDialogSectionHeader {
text: Translation.tr("Brightness")
}
WindowDialogSeparator {
Layout.topMargin: -22
Layout.leftMargin: 0
Layout.rightMargin: 0
}
Column {
id: brightnessColumn
Layout.topMargin: -16
Layout.fillWidth: true
// Layout.fillHeight: true
WindowDialogSlider {
anchors {
left: parent.left
right: parent.right
leftMargin: 4
rightMargin: 4
}
// text: Translation.tr("Brightness")
value: root.brightnessMonitor.brightness
onMoved: root.brightnessMonitor.setBrightness(value)
}
}
WindowDialogButtonRow {
Layout.fillWidth: true
Item {
Layout.fillWidth: true
}
DialogButton {
buttonText: Translation.tr("Done")
onClicked: root.dismiss()
}
}
}
@@ -7,8 +7,9 @@ Rectangle {
radius: Appearance.rounding.normal
color: Appearance.colors.colLayer1
signal openWifiDialog()
signal openBluetoothDialog()
signal openAudioOutputDialog()
signal openAudioInputDialog()
signal openBluetoothDialog()
signal openNightLightDialog()
signal openWifiDialog()
}
@@ -12,15 +12,23 @@ AbstractQuickPanel {
id: root
property bool editMode: false
Layout.fillWidth: true
implicitHeight: (editMode ? contentItem.implicitHeight : usedRows.implicitHeight) + root.padding * 2
// Sizes
implicitHeight: (editMode ? contentItem.implicitHeight : usedRows.implicitHeight) + root.padding * 2
Behavior on implicitHeight {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
property real spacing: 6
property real padding: 6
readonly property real baseCellWidth: {
// This is the wrong calculation, but it looks correct in reality???
// (theoretically spacing should be multiplied by 1 column less)
const availableWidth = root.width - (root.padding * 2) - (root.spacing * (root.columns))
return availableWidth / root.columns
}
readonly property real baseCellHeight: 56
// Toggles
readonly property list<string> availableToggleTypes: ["network", "bluetooth", "idleInhibitor", "easyEffects", "nightLight", "darkMode", "cloudflareWarp", "gameMode", "screenSnip", "colorPicker", "onScreenKeyboard", "mic", "audio", "notifications", "powerProfile"]
readonly property int columns: Config.options.sidebar.quickToggles.android.columns
readonly property list<var> toggles: Config.ready ? Config.options.sidebar.quickToggles.android.toggles : []
@@ -30,13 +38,6 @@ AbstractQuickPanel {
return types.map(type => { return { type: type, size: 1 } })
}
readonly property list<var> unusedToggleRows: toggleRowsForList(unusedToggles)
readonly property real baseCellWidth: {
// This is the wrong calculation, but it looks correct in reality???
// (theoretically spacing should be multiplied by 1 column less)
const availableWidth = root.width - (root.padding * 2) - (root.spacing * (root.columns))
return availableWidth / root.columns
}
readonly property real baseCellHeight: 56
function toggleRowsForList(togglesList) {
var rows = [];
@@ -78,7 +79,10 @@ AbstractQuickPanel {
delegate: ButtonGroup {
id: toggleRow
required property int index
property var modelData: root.toggleRows[index]
property var modelData: {
print(JSON.stringify(root.toggleRows[index]))
return root.toggleRows[index]
}
property int startingIndex: {
const rows = root.toggleRows;
let sum = 0;
@@ -100,10 +104,11 @@ AbstractQuickPanel {
baseCellWidth: root.baseCellWidth
baseCellHeight: root.baseCellHeight
spacing: root.spacing
onOpenWifiDialog: root.openWifiDialog()
onOpenBluetoothDialog: root.openBluetoothDialog()
onOpenAudioOutputDialog: root.openAudioOutputDialog()
onOpenAudioInputDialog: root.openAudioInputDialog()
onOpenBluetoothDialog: root.openBluetoothDialog()
onOpenNightLightDialog: root.openNightLightDialog()
onOpenWifiDialog: root.openWifiDialog()
}
}
}
@@ -19,7 +19,7 @@ AndroidQuickToggleButton {
}
altAction: () => {
Config.options.light.night.automatic = !Config.options.light.night.automatic
root.openMenu()
}
Component.onCompleted: {
@@ -27,7 +27,7 @@ AndroidQuickToggleButton {
}
StyledToolTip {
text: Translation.tr("Night Light | Right-click to toggle Auto mode")
text: Translation.tr("Night Light | Right-click to configure")
}
}
@@ -14,10 +14,11 @@ DelegateChooser {
required property real baseCellHeight
required property real spacing
required property int startingIndex
signal openWifiDialog()
signal openBluetoothDialog()
signal openAudioOutputDialog()
signal openAudioInputDialog()
signal openBluetoothDialog()
signal openNightLightDialog()
signal openWifiDialog()
role: "type"
@@ -90,6 +91,9 @@ DelegateChooser {
baseCellHeight: root.baseCellHeight
cellSpacing: root.spacing
cellSize: modelData.size
onOpenMenu: {
root.openNightLightDialog()
}
} }
DelegateChoice { roleValue: "darkMode"; AndroidDarkModeToggle {
@@ -4,6 +4,7 @@ import QtQuick
import qs.modules.common
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
/**
* Simple hyprsunset service with automatic mode.
@@ -111,18 +112,28 @@ Singleton {
}
}
function toggle() {
function toggle(active = undefined) {
if (root.manualActive === undefined) {
root.manualActive = root.active;
root.manualActiveHour = root.clockHour;
root.manualActiveMinute = root.clockMinute;
}
root.manualActive = !root.manualActive;
root.manualActive = active !== undefined ? active : !root.manualActive;
if (root.manualActive) {
root.enable();
} else {
root.disable();
}
}
// Change temp
Connections {
target: Config.options.light.night
onColorTemperatureChanged: {
if (!root.active) return;
Hyprland.dispatch(`hyprctl hyprsunset temperature ${Config.options.light.night.colorTemperature}`);
Quickshell.execDetached(["hyprctl", "hyprsunset", "temperature", `${Config.options.light.night.colorTemperature}`]);
}
}
}