utilities: add keep awake and quick toggles

This commit is contained in:
2 * r + 2 * t 2025-09-12 16:51:38 +10:00
parent 0ed829c24a
commit 83d3b4ebd5
8 changed files with 306 additions and 27 deletions

View file

@ -20,6 +20,7 @@ Singleton {
property alias session: adapter.session property alias session: adapter.session
property alias winfo: adapter.winfo property alias winfo: adapter.winfo
property alias lock: adapter.lock property alias lock: adapter.lock
property alias utilities: adapter.utilities
property alias services: adapter.services property alias services: adapter.services
property alias paths: adapter.paths property alias paths: adapter.paths
@ -44,6 +45,7 @@ Singleton {
property SessionConfig session: SessionConfig {} property SessionConfig session: SessionConfig {}
property WInfoConfig winfo: WInfoConfig {} property WInfoConfig winfo: WInfoConfig {}
property LockConfig lock: LockConfig {} property LockConfig lock: LockConfig {}
property UtilitiesConfig utilities: UtilitiesConfig {}
property ServiceConfig services: ServiceConfig {} property ServiceConfig services: ServiceConfig {}
property UserPaths paths: UserPaths {} property UserPaths paths: UserPaths {}
} }

View file

@ -0,0 +1,11 @@
import Quickshell.Io
JsonObject {
property bool enabled: true
property Sizes sizes: Sizes {}
component Sizes: JsonObject {
property int width: 400
}
}

View file

@ -99,7 +99,7 @@ Item {
Utilities.Wrapper { Utilities.Wrapper {
id: utilities id: utilities
visibility: root.visibilities.utilities visibilities: root.visibilities
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right

View file

@ -1,31 +1,17 @@
import qs.components import "cards"
import qs.services
import qs.config import qs.config
import Quickshell import QtQuick.Layouts
import Quickshell.Widgets
import QtQuick
Item { ColumnLayout {
id: root id: root
anchors.top: parent.top required property var visibilities
anchors.bottom: parent.bottom
anchors.right: parent.right
// implicitWidth: 300 spacing: Appearance.spacing.normal
// implicitHeight: 100
// Rectangle { IdleInhibit {}
// anchors.fill: parent
// }
Behavior on implicitHeight { Toggles {
Anim {} visibilities: root.visibilities
}
component Anim: NumberAnimation {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
} }
} }

View file

@ -5,18 +5,18 @@ import QtQuick
Item { Item {
id: root id: root
required property bool visibility required property var visibilities
visible: height > 0 visible: height > 0
implicitHeight: 0 implicitHeight: 0
implicitWidth: content.implicitWidth implicitWidth: Config.utilities.sizes.width
states: State { states: State {
name: "visible" name: "visible"
when: root.visibility when: root.visibilities.utilities
PropertyChanges { PropertyChanges {
root.implicitHeight: content.implicitHeight root.implicitHeight: content.implicitHeight + Appearance.padding.large * 2
} }
} }
@ -46,5 +46,12 @@ Item {
Content { Content {
id: content id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Appearance.padding.large
visibilities: root.visibilities
} }
} }

View file

@ -0,0 +1,122 @@
import qs.components
import qs.components.controls
import qs.services
import qs.config
import QtQuick
import QtQuick.Layouts
StyledRect {
id: root
Layout.fillWidth: true
implicitHeight: layout.implicitHeight + (IdleInhibitor.enabled ? activeChip.implicitHeight + activeChip.anchors.topMargin : 0) + Appearance.padding.large * 2
radius: Appearance.rounding.normal
color: Colours.palette.m3surfaceContainer
clip: true
RowLayout {
id: layout
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Appearance.padding.large
spacing: Appearance.spacing.normal
StyledRect {
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.smaller * 2
radius: Appearance.rounding.full
color: IdleInhibitor.enabled ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
MaterialIcon {
id: icon
anchors.centerIn: parent
text: "coffee"
color: IdleInhibitor.enabled ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
font.pointSize: Appearance.font.size.large
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
StyledText {
Layout.fillWidth: true
text: qsTr("Keep Awake")
font.pointSize: Appearance.font.size.normal
elide: Text.ElideRight
}
StyledText {
Layout.fillWidth: true
text: IdleInhibitor.enabled ? qsTr("Preventing sleep mode") : qsTr("Normal power management")
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small
elide: Text.ElideRight
}
}
StyledSwitch {
checked: IdleInhibitor.enabled
onToggled: IdleInhibitor.enabled = checked
}
}
Loader {
id: activeChip
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.topMargin: Appearance.spacing.larger
anchors.bottomMargin: IdleInhibitor.enabled ? Appearance.padding.large : -implicitHeight
anchors.leftMargin: Appearance.padding.large
opacity: IdleInhibitor.enabled ? 1 : 0
scale: IdleInhibitor.enabled ? 1 : 0.5
Component.onCompleted: active = Qt.binding(() => opacity > 0)
sourceComponent: StyledRect {
implicitWidth: activeText.implicitWidth + Appearance.padding.normal * 2
implicitHeight: activeText.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full
color: Colours.palette.m3primary
StyledText {
id: activeText
anchors.centerIn: parent
text: qsTr("Active since %1").arg(Qt.formatTime(IdleInhibitor.enabledSince, Config.services.useTwelveHourClock ? "hh:mm a" : "hh:mm"))
color: Colours.palette.m3onPrimary
font.pointSize: Math.round(Appearance.font.size.small * 0.9)
}
}
Behavior on anchors.bottomMargin {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
Behavior on scale {
Anim {}
}
}
Behavior on implicitHeight {
Anim {}
}
}

View file

@ -0,0 +1,144 @@
import qs.components
import qs.services
import qs.config
import qs.modules.controlcenter
import Quickshell
import Quickshell.Bluetooth
import QtQuick
import QtQuick.Layouts
StyledRect {
id: root
required property var visibilities
Layout.fillWidth: true
implicitHeight: layout.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal
color: Colours.palette.m3surfaceContainer
GridLayout {
id: layout
anchors.fill: parent
anchors.margins: Appearance.padding.large
columns: 2
rowSpacing: Appearance.spacing.normal
columnSpacing: Appearance.spacing.normal
uniformCellWidths: true
StyledText {
Layout.columnSpan: 2
text: qsTr("Quick Toggles")
font.pointSize: Appearance.font.size.normal
}
Toggle {
icon: "wifi"
text: qsTr("WiFi")
checked: Network.wifiEnabled
function onClicked(): void {
Network.toggleWifi();
}
}
Toggle {
icon: "bluetooth"
text: qsTr("Bluetooth")
checked: Bluetooth.defaultAdapter?.enabled ?? false
function onClicked(): void {
const adapter = Bluetooth.defaultAdapter;
if (adapter)
adapter.enabled = !adapter.enabled;
}
}
Toggle {
icon: "mic"
text: qsTr("Microphone")
checked: !Audio.sourceMuted
function onClicked(): void {
const audio = Audio.source?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
Toggle {
icon: "settings"
text: qsTr("Settings")
toggle: false
function onClicked(): void {
root.visibilities.utilities = false;
WindowFactory.create(null, {
screen: QsWindow.window?.screen ?? null
});
}
}
}
component Toggle: StyledRect {
id: toggle
required property string icon
required property string text
property bool checked
property bool toggle
property bool internalChecked
function onClicked(): void {
}
onCheckedChanged: internalChecked = checked
radius: internalChecked ? Appearance.rounding.small : implicitHeight / 2
color: internalChecked ? Colours.palette.m3primary : Colours.palette.m3surfaceContainerHigh
Layout.fillWidth: true
implicitWidth: label.implicitWidth + Appearance.padding.larger * 2
implicitHeight: label.implicitHeight + Appearance.padding.smaller * 2
StateLayer {
color: toggle.internalChecked ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
function onClicked(): void {
if (toggle.toggle)
toggle.internalChecked = !toggle.internalChecked;
toggle.onClicked();
}
}
RowLayout {
id: label
anchors.centerIn: parent
spacing: Appearance.spacing.small
MaterialIcon {
text: toggle.icon
color: toggle.internalChecked ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
fill: toggle.internalChecked ? 1 : 0
Behavior on fill {
Anim {}
}
}
StyledText {
text: toggle.text
color: toggle.internalChecked ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
font.pointSize: Appearance.font.size.small
}
}
Behavior on radius {
Anim {}
}
}
}

View file

@ -7,11 +7,18 @@ Singleton {
id: root id: root
property alias enabled: props.enabled property alias enabled: props.enabled
readonly property alias enabledSince: props.enabledSince
onEnabledChanged: {
if (enabled)
props.enabledSince = new Date();
}
PersistentProperties { PersistentProperties {
id: props id: props
property bool enabled property bool enabled
property date enabledSince
reloadableId: "idleInhibitor" reloadableId: "idleInhibitor"
} }