summaryrefslogtreecommitdiff
path: root/modules/lock/Status.qml
diff options
context:
space:
mode:
Diffstat (limited to 'modules/lock/Status.qml')
-rw-r--r--modules/lock/Status.qml249
1 files changed, 249 insertions, 0 deletions
diff --git a/modules/lock/Status.qml b/modules/lock/Status.qml
new file mode 100644
index 0000000..e11fa25
--- /dev/null
+++ b/modules/lock/Status.qml
@@ -0,0 +1,249 @@
+import "root:/widgets"
+import "root:/services"
+import "root:/config"
+import "root:/utils"
+import Quickshell
+import Quickshell.Widgets
+import Quickshell.Services.UPower
+import QtQuick
+import QtQuick.Layouts
+
+WrapperItem {
+ readonly property real nonAnimWidth: (notifs.count > 0 ? Config.notifs.sizes.width : status.implicitWidth) + margin
+ readonly property real nonAnimHeight: {
+ if (notifs.count > 0) {
+ const count = Math.min(notifs.count, Config.lock.maxNotifs);
+ let height = status.implicitHeight + Appearance.spacing.normal + Appearance.spacing.smaller * (count - 1);
+ for (let i = 0; i < count; i++)
+ height += notifs.itemAtIndex(i)?.nonAnimHeight ?? 0;
+ return height + margin;
+ }
+
+ return status.implicitHeight + margin;
+ }
+
+ implicitWidth: nonAnimWidth
+ implicitHeight: nonAnimHeight
+
+ margin: Appearance.padding.large * 2
+ rightMargin: 0
+ topMargin: 0
+
+ Behavior on implicitWidth {
+ Anim {
+ duration: Appearance.anim.durations.large
+ easing.bezierCurve: Appearance.anim.curves.emphasized
+ }
+ }
+
+ Behavior on implicitHeight {
+ Anim {
+ duration: Appearance.anim.durations.large
+ easing.bezierCurve: Appearance.anim.curves.emphasized
+ }
+ }
+
+ ColumnLayout {
+ spacing: Appearance.spacing.normal
+
+ RowLayout {
+ id: status
+
+ Layout.fillWidth: true
+ spacing: Appearance.spacing.small
+
+ Loader {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+
+ active: UPower.displayDevice.isLaptopBattery
+ asynchronous: true
+
+ sourceComponent: StyledText {
+ animate: true
+ text: qsTr("%1%2 remaining").arg(UPower.onBattery ? "" : "(+) ").arg(UPower.displayDevice.percentage)
+ color: !UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? Colours.palette.m3onSurface : Colours.palette.m3error
+ }
+ }
+
+ MaterialIcon {
+ Layout.alignment: Qt.AlignVCenter
+
+ animate: true
+ text: Network.active ? Icons.getNetworkIcon(Network.active.strength ?? 0) : "wifi_off"
+ font.pointSize: Appearance.font.size.large
+ }
+
+ Loader {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ Layout.maximumWidth: item?.implicitWidth ?? 0
+
+ active: !UPower.displayDevice.isLaptopBattery
+ asynchronous: true
+
+ sourceComponent: StyledText {
+ animate: true
+ text: Network.active?.ssid ?? ""
+ font.pointSize: Appearance.font.size.normal
+ elide: Text.ElideRight
+ }
+ }
+
+ MaterialIcon {
+ Layout.alignment: Qt.AlignVCenter
+
+ animate: true
+ text: Bluetooth.powered ? "bluetooth" : "bluetooth_disabled"
+ font.pointSize: Appearance.font.size.large
+ }
+
+ Loader {
+ Layout.alignment: Qt.AlignVCenter
+ active: !UPower.displayDevice.isLaptopBattery
+ asynchronous: true
+
+ sourceComponent: StyledText {
+ animate: true
+ text: qsTr("%n device(s) connected", "", Bluetooth.devices.filter(d => d.connected).length)
+ font.pointSize: Appearance.font.size.normal
+ }
+ }
+ }
+
+ ListView {
+ id: notifs
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ model: ScriptModel {
+ values: [...Notifs.popups].reverse()
+ }
+
+ orientation: Qt.Vertical
+ spacing: 0
+ clip: true
+ interactive: false
+
+ delegate: Item {
+ id: wrapper
+
+ required property Notifs.Notif modelData
+ required property int index
+ readonly property alias nonAnimHeight: notif.nonAnimHeight
+ property int idx
+
+ onIndexChanged: {
+ if (index !== -1)
+ idx = index;
+ }
+
+ implicitWidth: notif.implicitWidth
+ implicitHeight: notif.nonAnimHeight + (idx === 0 ? 0 : Appearance.spacing.smaller)
+
+ ListView.onRemove: removeAnim.start()
+
+ SequentialAnimation {
+ id: removeAnim
+
+ PropertyAction {
+ target: wrapper
+ property: "ListView.delayRemove"
+ value: true
+ }
+ PropertyAction {
+ target: wrapper
+ property: "enabled"
+ value: false
+ }
+ PropertyAction {
+ target: wrapper
+ property: "implicitHeight"
+ value: 0
+ }
+ PropertyAction {
+ target: wrapper
+ property: "z"
+ value: 1
+ }
+ Anim {
+ target: notif
+ property: "x"
+ to: (notif.x >= 0 ? Config.notifs.sizes.width : -Config.notifs.sizes.width) * 2
+ duration: Appearance.anim.durations.normal
+ easing.bezierCurve: Appearance.anim.curves.emphasized
+ }
+ PropertyAction {
+ target: wrapper
+ property: "ListView.delayRemove"
+ value: false
+ }
+ }
+
+ ClippingRectangle {
+ anchors.top: parent.top
+ anchors.topMargin: wrapper.idx === 0 ? 0 : Appearance.spacing.smaller
+
+ color: "transparent"
+ radius: notif.radius
+ implicitWidth: notif.implicitWidth
+ implicitHeight: notif.nonAnimHeight
+
+ Notification {
+ id: notif
+
+ modelData: wrapper.modelData
+ }
+ }
+ }
+
+ move: Transition {
+ Anim {
+ property: "y"
+ }
+ }
+
+ displaced: Transition {
+ Anim {
+ property: "y"
+ }
+ }
+
+ StyledRect {
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.margins: Appearance.padding.normal
+
+ color: Colours.palette.m3tertiaryContainer
+ radius: Appearance.rounding.small
+
+ implicitWidth: count.implicitWidth + Appearance.padding.normal * 2
+ implicitHeight: count.implicitHeight + Appearance.padding.small * 2
+
+ scale: Notifs.popups.length > Config.lock.maxNotifs ? 1 : 0
+
+ StyledText {
+ id: count
+
+ anchors.centerIn: parent
+ text: qsTr("+%1").arg(Notifs.popups.length - Config.lock.maxNotifs)
+ color: Colours.palette.m3onTertiaryContainer
+ }
+
+ Behavior on scale {
+ Anim {
+ duration: Appearance.anim.durations.expressiveFastSpatial
+ easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
+ }
+ }
+ }
+ }
+ }
+
+ component Anim: NumberAnimation {
+ duration: Appearance.anim.durations.normal
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Appearance.anim.curves.standard
+ }
+}