From 9e0887c474df9a655f8fae316d92c7e3e734cba3 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 10:09:32 +0100 Subject: [PATCH 01/38] deleted everything lol --- Bar/Center.qml | 263 -------------------- Bar/Center/Expanded.qml | 55 ----- Bar/Center/Mpris.qml | 62 ----- Bar/Center/NotificationDisplay.qml | 49 ---- Bar/Center/NotificationList.qml | 307 ----------------------- Bar/Left.qml | 70 ------ Bar/Left/WorkspaceContainer.qml | 86 ------- Bar/Left/WorkspaceSelector.qml | 87 ------- Bar/Right.qml | 27 -- Bar/Right/Battery.qml | 28 --- Bar/Right/Bluetooth.qml | 98 -------- Bar/Right/Bluetooth/Expanded.qml | 384 ----------------------------- 12 files changed, 1516 deletions(-) delete mode 100644 Bar/Center.qml delete mode 100644 Bar/Center/Expanded.qml delete mode 100644 Bar/Center/Mpris.qml delete mode 100644 Bar/Center/NotificationDisplay.qml delete mode 100644 Bar/Center/NotificationList.qml delete mode 100644 Bar/Left.qml delete mode 100644 Bar/Left/WorkspaceContainer.qml delete mode 100644 Bar/Left/WorkspaceSelector.qml delete mode 100644 Bar/Right.qml delete mode 100644 Bar/Right/Battery.qml delete mode 100644 Bar/Right/Bluetooth.qml delete mode 100644 Bar/Right/Bluetooth/Expanded.qml diff --git a/Bar/Center.qml b/Bar/Center.qml deleted file mode 100644 index 103cd75..0000000 --- a/Bar/Center.qml +++ /dev/null @@ -1,263 +0,0 @@ -pragma ComponentBehavior: Bound -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Hyprland -import Quickshell.Services.Mpris -import Quickshell.Services.Notifications -import "../Color.js" as Colors -import "../Components/" -import "../Services/" -import "./Center" - -Container { - id: root - - property Notification latestNotification: NotificationManager.getLatestNotification() || null - required property HyprlandMonitor monitor - property NotificationServer notifServer: NotificationManager.notif - property string previousState - - boxColor: Colors.mauve - defaultItem: time - exclusiveMonitor: root.monitor - exclusiveToScreen: true - - states: [ - State { - name: "" - - PropertyChanges { - root.boxHeight: 28 - root.boxRadius: 9 - root.boxWidth: 100 - root.visibleTopMargin: 0 - } - - StateChangeScript { - script: { - if (root.previousState != "hovered") { - root.stack.replace(time); - } - root.previousState = ""; - } - } - }, - State { - name: "hovered" - - PropertyChanges { - root.boxHeight: 35 - root.boxRadius: 15 - root.boxWidth: 110 - root.visibleTopMargin: 0 - } - - StateChangeScript { - script: { - root.previousState = "hovered"; - } - } - }, - State { - name: "mprisToast" - - PropertyChanges { - root.boxHeight: 35 - root.boxRadius: 15 - root.boxWidth: 350 - root.visibleTopMargin: 0 - } - - StateChangeScript { - script: { - root.previousState = "mpris"; - root.stack.replace(mpris); - } - } - }, - State { - name: "expanded" - - PropertyChanges { - root.boxHeight: 140 - root.boxRadius: 30 - root.boxWidth: 300 - root.visibleTopMargin: 0 - } - - StateChangeScript { - script: { - if (root.state != "notifications") { - root.stack.replace(fullTime); - root.previousState = "expanded"; - } - } - } - }, - State { - extend: "expanded" - name: "notifications" - - PropertyChanges { - root.boxHeight: 320 - } - }, - State { - name: "notified" - - PropertyChanges { - root.boxHeight: 90 - root.boxRadius: 30 - root.boxWidth: 330 - root.visibleTopMargin: 20 - } - - StateChangeScript { - script: { - root.stack.replace(notification); - root.previousState = "notified"; - } - } - } - ] - - hover.onHoveredChanged: { - if (hover.hovered == true) { - if (root.state == "notified") { - root.state = "notified"; - notificationViewTimer.stop(); - } else if (MprisManager.getPlaying() == true) { - root.state = "mprisToast"; - } else { - root.state = "hovered"; - } - } else { - root.state = ""; - } - } - onLatestNotificationChanged: { - if (latestNotification != null && Hyprland.focusedMonitor == monitor) { - if (root.latestNotification.lastGeneration == false) { - root.state = "notified"; - notificationViewTimer.restart(); - } - } - } - tap.onTapped: { - root.state == "hovered" ? root.state = "expanded" : undefined; - } - - Connections { - function onTrackChanged() { - if (Hyprland.focusedMonitor == root.monitor) { - musicToastTimer.restart(); - if (root.state == "") { - root.state = "mprisToast"; - } - } - } - - target: MprisManager.defaultPlayer - } - - Timer { - id: notificationViewTimer - - interval: 3000 - repeat: false - running: false - - onTriggered: { - root.state = ""; - } - } - - Timer { - id: musicToastTimer - - interval: 3000 - repeat: false - running: false - - onTriggered: { - if (!root.hover.hovered) { - root.state = ""; - } - } - } - - Component { - id: time - - Item { - CenteredText { - text: Time.time - } - } - } - - Component { - id: mpris - - Mpris { - TapHandler { - onTapped: root.state = "expanded" - } - - TapHandler { - acceptedButtons: Qt.RightButton - - onTapped: MprisManager.skip() - } - - TapHandler { - acceptedButtons: Qt.MiddleButton - - onTapped: MprisManager.prev() - } - } - } - - Component { - id: fullTime - - Expanded { - NotificationList { - id: notifList - - animEnabled: false - radius: root.boxRadius - rootState: root.state - server: root.notifServer - state: "" - - TapHandler { - onTapped: { - notifList.animEnabled = true; - root.state = "notifications"; - Qt.callLater(() => { - notifList.animEnabled = false; - }); - } - } - } - } - } - - Component { - id: notification - - NotificationDisplay { - body: root.latestNotification.body - summary: root.latestNotification.summary - - TapHandler { - onTapped: { - root.state = "notifications"; - root.stack.replace(fullTime); - } - } - } - } -} diff --git a/Bar/Center/Expanded.qml b/Bar/Center/Expanded.qml deleted file mode 100644 index 2908700..0000000 --- a/Bar/Center/Expanded.qml +++ /dev/null @@ -1,55 +0,0 @@ -import QtQuick -import Quickshell -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: fullTimeRoot - - Rectangle { - anchors.fill: parent - radius: 30 - - gradient: MidpointGradient { - color: Colors.red - } - } - - Item { - id: timeColumnContainer - - anchors.fill: parent - - Column { - id: timeColumn - - spacing: 5 - - anchors { - centerIn: parent - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - color: Colors.surface0 - text: Time.time - - font { - pointSize: 30 - } - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - color: Colors.surface1 - text: Time.date - - font { - pointSize: 9 - weight: 400 - } - } - } - } -} diff --git a/Bar/Center/Mpris.qml b/Bar/Center/Mpris.qml deleted file mode 100644 index 51adfe2..0000000 --- a/Bar/Center/Mpris.qml +++ /dev/null @@ -1,62 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell.Services.Mpris -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: root - - property MprisPlayer player: MprisManager.defaultPlayer - - Rectangle { - color: Colors.red - radius: 5 - - anchors { - bottomMargin: 15 - fill: parent - leftMargin: 10 - rightMargin: parent.width - ((parent.width * MprisManager.pos) - 10) - topMargin: 15 - } - } - - RowLayout { - anchors { - bottomMargin: 2 - fill: parent - leftMargin: 7 - rightMargin: 7 - topMargin: 2 - } - - Item { - Layout.fillHeight: true - Layout.preferredWidth: height - - Image { - anchors.fill: parent - fillMode: Image.PreserveAspectFit - source: MprisManager.defaultPlayer.trackArtUrl - } - } - - Item { - Layout.fillHeight: true - Layout.fillWidth: true - - StyledText { - elide: Qt.ElideRight - horizontalAlignment: Qt.AlignHCenter - text: MprisManager.defaultPlayer.trackArtist + " - " + MprisManager.defaultPlayer.trackTitle - verticalAlignment: Qt.AlignVCenter - - anchors { - fill: parent - } - } - } - } -} diff --git a/Bar/Center/NotificationDisplay.qml b/Bar/Center/NotificationDisplay.qml deleted file mode 100644 index 65a27e3..0000000 --- a/Bar/Center/NotificationDisplay.qml +++ /dev/null @@ -1,49 +0,0 @@ -import QtQuick -import Quickshell -import Quickshell.Services.Notifications -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: root - - required property string body - required property string summary - - Rectangle { - anchors.fill: parent - radius: 30 - - gradient: MidpointGradient { - color: Colors.green - midpoint: 0.7 - } - } - - Column { - anchors.centerIn: parent - spacing: 5 - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - font.pointSize: 11 - text: root.summary - } - - StyledText { - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - maximumLineCount: 2 - text: root.body - verticalAlignment: Text.AlignVCenter - width: root.width - 20 - wrapMode: Text.WordWrap - - font { - pointSize: 10 - weight: 500 - } - } - } -} diff --git a/Bar/Center/NotificationList.qml b/Bar/Center/NotificationList.qml deleted file mode 100644 index c6372c9..0000000 --- a/Bar/Center/NotificationList.qml +++ /dev/null @@ -1,307 +0,0 @@ -import QtQuick -import QtQuick.Effects -import Quickshell -import Quickshell.Services.Notifications -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: root - - required property bool animEnabled - required property double radius - required property string rootState - required property NotificationServer server - - Behavior on anchors.topMargin { - enabled: root.animEnabled - - SpringAnimation { - damping: 0.35 - spring: 4 - } - } - states: [ - State { - name: "" - when: root.rootState != "notifications" - - PropertyChanges { - root.anchors.topMargin: root.parent.height - 21 - } - }, - State { - name: "expanded" - when: root.rootState == "notifications" - - PropertyChanges { - root.anchors.topMargin: 5 - } - } - ] - - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - top: parent.top - topMargin: parent.height - 21 - } - - Rectangle { - id: background - - anchors.fill: parent - color: Colors.surface0 - radius: root.radius - 3 - - states: [ - State { - name: "" - when: root.rootState != "notifications" - - PropertyChanges {} - }, - State { - name: "expanded" - when: root.rootState == "notifications" - - PropertyChanges { - background.anchors.bottomMargin: 5 - background.anchors.leftMargin: 5 - background.anchors.rightMargin: 5 - } - } - ] - - anchors { - bottomMargin: 15 - leftMargin: 20 - rightMargin: 20 - } - } - - Item { - id: notifListContainer - - anchors.fill: parent - clip: true - opacity: 0 - - anchors { - bottomMargin: 5 - leftMargin: 5 - rightMargin: 5 - topMargin: 5 - } - - CenteredText { - color: Colors.overlay0 - text: "No Notifications" - visible: root.server.trackedNotifications.values.length <= 0 - } - - ListView { - id: notifScrollingList - - anchors.fill: parent - boundsBehavior: Flickable.StopAtBounds - height: Math.min(contentHeight, parent.height) - implicitHeight: background.height - model: root.server.trackedNotifications.values.length - spacing: 7 - - delegate: Item { - id: notifRoot - - property Notification currentNotif: root.server.trackedNotifications.values[(notifRoot.notifLen - - 1) - index] - required property real index - property real notifLen: root.server.trackedNotifications.values.length - - height: 50 - width: ListView.view.width - - states: [ - State { - name: "" - when: notifHover.hovered == false - }, - State { - name: "hovered" - when: notifHover.hovered == false - - PropertyChanges {} - } - ] - - HoverHandler { - id: notifHover - } - - Rectangle { - id: dismissButton - - color: Colors.red - implicitWidth: 100 - radius: 10 - - Behavior on anchors.rightMargin { - NumberAnimation { - duration: 100 - } - } - states: [ - State { - name: "" - when: notifHover.hovered == false - }, - State { - name: "hovered" - when: notifHover.hovered == true - - PropertyChanges { - dismissButton.anchors.rightMargin: 5 - } - } - ] - - StyledText { - color: Colors.surface0 - font.pointSize: 15 - horizontalAlignment: Qt.AlignRight - text: "󰩹" - verticalAlignment: Qt.AlignVCenter - - anchors { - fill: parent - rightMargin: 14 - } - } - - TapHandler { - onTapped: { - notifRoot.currentNotif.dismiss(); - } - } - - anchors { - bottom: parent.bottom - bottomMargin: 3 - right: parent.right - rightMargin: 10 - top: parent.top - topMargin: 3 - } - } - - Rectangle { - id: textContainer - - anchors.fill: parent - clip: true - color: Colors.surface2 - radius: 9 - - Behavior on anchors.rightMargin { - NumberAnimation { - duration: 100 - } - } - states: [ - State { - name: "" - when: notifHover.hovered == false - }, - State { - name: "hovered" - when: notifHover.hovered == true - - PropertyChanges { - textContainer.anchors.rightMargin: 40 - } - } - ] - - Column { - id: textColumn - - anchors { - centerIn: parent - left: parent.left - right: parent.right - } - - StyledText { - color: Colors.text - horizontalAlignment: Text.AlignHCenter - text: notifRoot.currentNotif.summary - verticalAlignment: Text.AlignVCenter - width: notifRoot.width - 10 - } - - StyledText { - color: Colors.subtext1 - horizontalAlignment: Text.AlignHCenter - text: notifRoot.currentNotif.body - verticalAlignment: Text.AlignVCenter - width: notifRoot.width - 10 - } - } - } - } - - anchors { - bottomMargin: 5 - leftMargin: 10 - rightMargin: 10 - topMargin: 5 - } - } - } - - MultiEffect { - id: notifListClipper - - anchors.fill: notifListContainer - maskEnabled: true - maskSource: clipsource - opacity: 0 - source: notifListContainer - - Behavior on opacity { - NumberAnimation { - duration: 100 - } - } - states: [ - State { - name: "" - when: root.rootState != "notifications" - - PropertyChanges { - notifListClipper.opacity: 0 - } - }, - State { - name: "expanded" - when: root.rootState == "notifications" - - PropertyChanges { - notifListClipper.opacity: 1 - } - } - ] - } - - Rectangle { - id: clipsource - - anchors.fill: background - color: "black" - layer.enabled: true - radius: background.radius - visible: false - } -} diff --git a/Bar/Left.qml b/Bar/Left.qml deleted file mode 100644 index 99ff888..0000000 --- a/Bar/Left.qml +++ /dev/null @@ -1,70 +0,0 @@ -pragma ComponentBehavior: Bound -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Hyprland -import Quickshell.Services.Notifications -import "../Color.js" as Colors -import "../Components/" -import "../Services/" -import "./Center" -import "./Left/" - -Container { - id: root - - property double extraHoveredWidth: 0 - required property HyprlandMonitor monitor - property double rowLeftMargin: 4 - property double rowSpacing: 3 - property double rowYmargin: 3 - property double selectorFocusedExtra: 15 - property double selectorHeight: 20 - property double selectorWidth: 20 - property double spacing: 3 - property double workspaceNumber: WorkspaceManager.getNumberOfWorkspaces(monitor) - - boxHeight: 25 - boxWidth: (selectorWidth * workspaceNumber) + ((2 * rowLeftMargin) + (rowSpacing * ( - workspaceNumber - 1))) + extraHoveredWidth + (hoverHandler.hovered == true - ? selectorFocusedExtra : 0) - exclusiveMonitor: monitor - - defaultItem: WorkspaceContainer { - extraHoveredWidth: root.extraHoveredWidth - monitor: root.monitor - rowLeftMargin: root.rowLeftMargin - rowSpacing: root.rowSpacing - rowYmargin: root.rowYmargin - selectorFocusedExtra: root.selectorFocusedExtra - selectorHeight: root.selectorHeight - selectorWidth: root.selectorWidth - } - Behavior on rowYmargin { - SpringAnimation { - damping: 0.3 - spring: 4 - } - } - states: [ - State { - name: "" - when: !hoverHandler.hovered - }, - State { - name: "hovered" - when: hoverHandler.hovered - - PropertyChanges { - root.boxHeight: 40 - root.extraHoveredWidth: 25 - root.rowYmargin: 5 - root.selectorWidth: 40 - } - } - ] - - HoverHandler { - id: hoverHandler - } -} diff --git a/Bar/Left/WorkspaceContainer.qml b/Bar/Left/WorkspaceContainer.qml deleted file mode 100644 index 65ccc38..0000000 --- a/Bar/Left/WorkspaceContainer.qml +++ /dev/null @@ -1,86 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Hyprland -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: root - - required property double extraHoveredWidth - required property HyprlandMonitor monitor - required property double rowLeftMargin - required property double rowSpacing - required property double rowYmargin - required property double selectorFocusedExtra - required property double selectorHeight - required property double selectorWidth - - Item { - id: newWorkspaceButton - - implicitWidth: 20 - opacity: root.extraHoveredWidth > 0 ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: 100 - } - } - - TapHandler { - id: tapHandler - - onTapped: WorkspaceManager.activateNextFreeWorkspace() - } - - anchors { - bottom: parent.bottom - bottomMargin: 5 + root.rowYmargin - right: parent.right - rightMargin: 4 - top: parent.top - topMargin: 5 + root.rowYmargin - } - - Rectangle { - anchors.fill: parent - color: Colors.green - radius: 4 - - StyledText { - anchors.centerIn: parent - text: "+" - } - } - } - - Row { - spacing: root.rowSpacing - - anchors { - bottom: parent.bottom - bottomMargin: root.rowYmargin - left: parent.left - leftMargin: root.rowLeftMargin - top: parent.top - topMargin: root.rowYmargin - } - - Repeater { - model: WorkspaceManager.getWorkspacesForMonitor(root.monitor) - - WorkspaceSelector { - required property HyprlandWorkspace modelData - - extraHoveredWidth: root.extraHoveredWidth - selectorFocusedExtra: root.selectorFocusedExtra - selectorHeight: root.selectorHeight - selectorWidth: root.selectorWidth - workspace: modelData - } - } - } -} diff --git a/Bar/Left/WorkspaceSelector.qml b/Bar/Left/WorkspaceSelector.qml deleted file mode 100644 index 3111d51..0000000 --- a/Bar/Left/WorkspaceSelector.qml +++ /dev/null @@ -1,87 +0,0 @@ -import QtQuick -import QtQuick.Controls -import Quickshell -import Quickshell.Hyprland -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" - -Item { - id: root - - required property double extraHoveredWidth - property bool hovered: extraHoveredWidth > 0 ? true : false - property color selectorColor: Colors.surface2 - required property double selectorFocusedExtra - required property double selectorHeight - required property double selectorWidth - required property HyprlandWorkspace workspace - property string workspaceState: WorkspaceManager.getWorkspaceState(workspace) - - implicitWidth: selectorWidth + (root.hovered == true ? (root.workspaceState == "focused" - ? selectorFocusedExtra : 0) : 0) - - Behavior on implicitWidth { - SpringAnimation { - damping: 0.3 - spring: 4 - } - } - states: [ - State { - name: "" - when: root.workspaceState == "inactive" - - PropertyChanges { - root.selectorColor: Colors.surface2 - } - }, - State { - name: "active" - when: root.workspaceState == "active" - - PropertyChanges { - root.selectorColor: Colors.overlay2 - } - }, - State { - name: "focused" - when: root.workspaceState == "focused" - - PropertyChanges { - root.selectorColor: Colors.lavender - } - } - ] - - TapHandler { - id: tapHandler - - onTapped: root.workspace.activate() - } - - anchors { - bottom: parent.bottom - top: parent.top - } - - Rectangle { - color: root.selectorColor - radius: 6 - - Behavior on color { - ColorAnimation { - duration: 100 - } - } - - anchors { - fill: parent - } - - CenteredText { - font.pointSize: 10.5 - text: root.workspace.id - } - } -} diff --git a/Bar/Right.qml b/Bar/Right.qml deleted file mode 100644 index 093d19d..0000000 --- a/Bar/Right.qml +++ /dev/null @@ -1,27 +0,0 @@ -pragma ComponentBehavior: Bound -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Hyprland -import Quickshell.Services.Notifications -import "../Color.js" as Colors -import "../Components/" -import "../Services/" -import "./Center" -import "./Right/" - -Row { - id: root - - required property HyprlandMonitor monitor - - spacing: 10 - - Battery { - exclusiveMonitor: root.monitor - } - - Bluetooth { - exclusiveMonitor: root.monitor - } -} diff --git a/Bar/Right/Battery.qml b/Bar/Right/Battery.qml deleted file mode 100644 index 3b5f605..0000000 --- a/Bar/Right/Battery.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma ComponentBehavior: Bound -import QtQuick -import Quickshell -import Quickshell.Services.UPower -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" -import "Bluetooth" - -Container { - id: root - - animOffset: 160 - boxColor: Colors.green - boxHeight: 25 - boxWidth: 40 - defaultItem: icon - exclusiveToScreen: true - forceHidden: BatteryManager.battery.isLaptopBattery - - Component { - id: icon - - CenteredText { - text: BatteryManager.batteryPercentage - } - } -} diff --git a/Bar/Right/Bluetooth.qml b/Bar/Right/Bluetooth.qml deleted file mode 100644 index a3df4db..0000000 --- a/Bar/Right/Bluetooth.qml +++ /dev/null @@ -1,98 +0,0 @@ -pragma ComponentBehavior: Bound -import QtQuick -import Quickshell -import Quickshell.Bluetooth -import "../../Color.js" as Colors -import "../../Components/" -import "../../Services/" -import "Bluetooth" - -Container { - id: root - - property bool shown: false - - animOffset: 200 - boxColor: Colors.peach - boxHeight: 25 - boxWidth: 30 - defaultItem: icon - exclusiveToScreen: true - forceHidden: !(root.shown || BluetoothManager.getConnected()) - hoverableWhenHidden: true - state: "" - - states: [ - State { - name: "" - - PropertyChanges { - root.boxHeight: 25 - root.boxWidth: 30 - } - - StateChangeScript { - script: { - root.stack.replace(icon); - } - } - }, - State { - name: "expanded" - - PropertyChanges { - root.boxHeight: 250 - root.boxRadius: 20 - root.boxWidth: 350 - } - - StateChangeScript { - script: { - root.stack.replace(expanded); - root.shown = true; - } - } - } - ] - - hover.onHoveredChanged: { - if (hover.hovered == false) { - root.state = ""; - hoverIntervalTimer.start(); - } else { - root.shown = true; - hoverIntervalTimer.start(); - } - } - tap.onTapped: state = "expanded" - - Timer { - id: hoverIntervalTimer - - interval: 500 - repeat: false - running: false - - onTriggered: { - if (root.hover.hovered == false) { - root.shown = false; - } - } - } - - Component { - id: icon - - Item { - CenteredText { - text: BluetoothManager.getConnected() == true ? "󰂱" : "󰂲" - } - } - } - - Component { - id: expanded - - Expanded {} - } -} diff --git a/Bar/Right/Bluetooth/Expanded.qml b/Bar/Right/Bluetooth/Expanded.qml deleted file mode 100644 index 71b4f61..0000000 --- a/Bar/Right/Bluetooth/Expanded.qml +++ /dev/null @@ -1,384 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell.Bluetooth -import "../../../Color.js" as Colors -import "../../../Components/" -import "../../../Services/" - -Item { - id: root - - property double topBarHeight: 35 - - Rectangle { - color: Colors.surface0 - radius: 17 - - anchors { - bottomMargin: 5 - fill: parent - leftMargin: 5 - rightMargin: 5 - topMargin: 5 - } - - Rectangle { - id: topBar - - property double topBarHeight: root.topBarHeight - - color: Colors.peach - implicitHeight: topBarHeight - radius: 9 - - anchors { - left: parent.left - leftMargin: 5 - right: parent.right - rightMargin: 5 - top: parent.top - topMargin: 5 - } - - RowLayout { - id: topBarRow - - property double topBarRowPadding: 4 - - spacing: 3 - - anchors { - left: parent.left - leftMargin: topBarRowPadding - right: parent.right - rightMargin: topBarRowPadding - top: parent.top - topMargin: topBarRowPadding - } - - Rectangle { - Layout.fillWidth: true - // color: Qt.lighter(Colors.peach, 1.2) - color: Colors.surface1 - implicitHeight: topBar.topBarHeight - (topBarRow.topBarRowPadding * 2) - radius: 6 - - StyledText { - anchors.verticalCenter: parent.verticalCenter - color: Colors.text - horizontalAlignment: Qt.AlignLeft - text: " " + BluetoothManager.defaultAdapterName - } - } - - Rectangle { - id: scanButton - - color: Qt.lighter(Colors.peach, 1.15) - implicitHeight: topBar.topBarHeight - (topBarRow.topBarRowPadding * 2) - implicitWidth: topBar.topBarHeight - (topBarRow.topBarRowPadding * 2) - radius: 6 - - Behavior on color { - ColorAnimation { - duration: 100 - } - } - states: [ - State { - name: "hovered" - - PropertyChanges { - scanButton.color: Colors.green - } - } - ] - - border { - color: Colors.surface0 - width: 2 - } - - HoverHandler { - onHoveredChanged: hovered == true ? scanButton.state = "hovered" : scanButton.state = "" - } - - TapHandler { - onTapped: { - BluetoothManager.toggleDiscover(); - } - } - - CenteredText { - id: scanButtonText - - text: "" - - NumberAnimation { - id: animateRotation - - duration: 1000 - from: 0 - loops: Animation.Infinite - properties: "rotation" - running: BluetoothManager.defaultAdapter.discovering - target: scanButtonText - to: 360 - - onStopped: { - scanButton.rotation = 0; - } - } - } - } - } - } - - ListView { - boundsBehavior: Flickable.StopAtBounds - clip: true - model: BluetoothManager.getDevicesList() - spacing: 5 - - delegate: Item { - id: deviceRoot - - required property real index - required property BluetoothDevice modelData - - height: 55 - width: ListView.view.width - - Rectangle { - id: containerBox - - anchors.fill: parent - clip: true - color: Colors.peach - radius: 7 - - Rectangle { - anchors.centerIn: parent - color: Colors.green - implicitHeight: parent.height - 10 - implicitWidth: parent.width * (deviceRoot.modelData.batteryAvailable == true - ? deviceRoot.modelData.battery : 0) - 10 - opacity: 0.7 - radius: 7 - visible: deviceRoot.modelData.batteryAvailable == true - } - - RowLayout { - anchors { - bottomMargin: 4 - fill: parent - leftMargin: 4 - rightMargin: 4 - topMargin: 4 - } - - Rectangle { - Layout.fillHeight: true - Layout.preferredWidth: height - color: deviceRoot.modelData.connected ? Colors.green : Qt.lighter(Colors.peach, 1.25) - radius: 5 - - CenteredText { - color: Colors.surface0 - font.pointSize: 30 - text: BluetoothManager.getIcon(deviceRoot.modelData.icon) - } - } - - ColumnLayout { - Layout.fillWidth: true - - Rectangle { - Layout.fillHeight: true - Layout.fillWidth: true - color: Qt.lighter(Colors.peach, 1.15) - radius: 4 - - StyledText { - anchors.fill: parent - anchors.verticalCenter: parent.verticalCenter - elide: Qt.ElideRight - text: deviceRoot.modelData.name - } - } - - Rectangle { - Layout.fillHeight: true - Layout.fillWidth: true - color: "transparent" - - StyledText { - anchors.fill: parent - anchors.verticalCenter: parent.verticalCenter - color: Colors.surface2 - font.weight: 300 - text: deviceRoot.modelData.address - } - } - } - - Item { - Layout.fillHeight: true - Layout.preferredWidth: height - - RowLayout { - anchors.fill: parent - - Rectangle { - id: itemEntry - - Layout.fillHeight: true - Layout.fillWidth: true - color: Colors.red - radius: 3 - - Loader { - id: deleteButtonLoader - - anchors.fill: parent - sourceComponent: forgetButton - - states: [ - State { - name: "" - when: deviceRoot.modelData.connected == false - - PropertyChanges { - deleteButtonLoader.sourceComponent: forgetButton - } - }, - State { - name: "connected" - when: deviceRoot.modelData.connected == true - - PropertyChanges { - deleteButtonLoader.sourceComponent: disconnectButton - } - } - ] - } - - Component { - id: disconnectButton - - Item { - anchors.fill: parent - - TapHandler { - onTapped: deviceRoot.modelData.disconnect() - } - - CenteredText { - text: "" - } - } - } - - Component { - id: forgetButton - - Item { - anchors.fill: parent - - TapHandler { - onTapped: deviceRoot.modelData.forget() - } - - CenteredText { - text: "󰩹" - } - } - } - } - - Rectangle { - id: greenButton - - property Component loadedItem: connectButton - - Layout.fillHeight: true - Layout.fillWidth: true - color: Colors.green - radius: 3 - - states: [ - State { - name: "" - when: deviceRoot.modelData.paired == true - - PropertyChanges { - greenButton.color: Colors.green - greenButton.loadedItem: connectButton - } - }, - State { - name: "unpaired" - when: deviceRoot.modelData.paired == false - - PropertyChanges { - greenButton.color: Colors.blue - greenButton.loadedItem: pairButton - } - } - ] - - Loader { - anchors.fill: parent - sourceComponent: greenButton.loadedItem - } - - Component { - id: connectButton - - Item { - anchors.fill: parent - - CenteredText { - text: "󱘖" - } - - TapHandler { - onTapped: deviceRoot.modelData.connect() - } - } - } - - Component { - id: pairButton - - Item { - anchors.fill: parent - - CenteredText { - text: "" - } - - TapHandler { - onTapped: { - deviceRoot.modelData.pair(); - } - } - } - } - } - } - } - } - } - } - - anchors { - bottomMargin: 5 - fill: parent - leftMargin: 5 - rightMargin: 5 - topMargin: 10 + root.topBarHeight - } - } - } -} From 8ba73b061ff034be6cb3c02f577d5efb7b3faefa Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 10:09:56 +0100 Subject: [PATCH 02/38] have a clock again --- Bar.qml | 70 ++++++++++++++-------------------------- Bar/Time.qml | 41 +++++++++++++++++++++++ Components/Container.qml | 15 +++++++-- 3 files changed, 78 insertions(+), 48 deletions(-) create mode 100644 Bar/Time.qml diff --git a/Bar.qml b/Bar.qml index 45a8464..557a746 100644 --- a/Bar.qml +++ b/Bar.qml @@ -3,7 +3,7 @@ import QtQuick.Effects import QtQuick.Layouts import Quickshell import Quickshell.Hyprland -import "Bar" +import "./Bar" import "Color.js" as Colors Scope { @@ -26,17 +26,9 @@ Scope { screen: modelData mask: Region { - Region { - item: left - } - Region { item: center } - - Region { - item: right - } } anchors { @@ -51,47 +43,35 @@ Scope { topMargin: 3 } - Row { - id: left - - height: childrenRect.height - + RowLayout { anchors { left: parent.left - leftMargin: 7 - } - - Left { - monitor: win.monitor - } - } - - Row { - id: center - - height: childrenRect.height - - anchors { - horizontalCenter: parent.horizontalCenter - } - - Center { - monitor: win.monitor - } - } - - Row { - id: right - - height: childrenRect.height - - anchors { right: parent.right - rightMargin: 7 + top: parent.top } - Right { - monitor: win.monitor + Row { + id: left + } + + Item { + Layout.fillWidth: true + } + + Row { + id: center + + Time { + monitor: win.monitor + } + } + + Item { + Layout.fillWidth: true + } + + Row { + id: right } } } diff --git a/Bar/Time.qml b/Bar/Time.qml new file mode 100644 index 0000000..dbb3ba5 --- /dev/null +++ b/Bar/Time.qml @@ -0,0 +1,41 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + required property HyprlandMonitor monitor + + boxColor: Colors.mauve + defaultItem: time + exclusiveMonitor: root.monitor + + states: [ + State { + name: "hovered" + when: root.hovered == true + + PropertyChanges { + root.boxHeight: 32 + root.boxRadius: 12 + root.boxWidth: 110 + } + } + ] + + Component { + id: time + + StyledText { + horizontalAlignment: Qt.AlignCenter + text: Time.time + verticalAlignment: Qt.AlignVCenter + } + } +} diff --git a/Components/Container.qml b/Components/Container.qml index dfde525..a178d59 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -35,6 +35,7 @@ Item { property bool forceHidden: false property alias hover: hoverHandler property bool hoverableWhenHidden: false + property bool hovered: false property alias rect: container property alias stack: containerContent property alias tap: tapHandler @@ -79,6 +80,14 @@ Item { HoverHandler { id: hoverHandler + + onHoveredChanged: { + if (hoverHandler.hovered == true) { + root.hovered = true; + } else { + root.hovered = false; + } + } } TapHandler { @@ -89,10 +98,10 @@ Item { anchors.fill: container blur: 30 color: Colors.mantle - offset.x: 7 - offset.y: 3 + offset.x: 5 + offset.y: 2 radius: container.radius - spread: 10 + spread: 5 } Rectangle { From 8e59d2dcec1dd1ba05bba7409411da30fdb935cc Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 10:33:54 +0100 Subject: [PATCH 03/38] using the old functions to get some rectangles to draw --- Bar.qml | 20 ++++++++++++++++++ Bar/WorkspaceSelector.qml | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 Bar/WorkspaceSelector.qml diff --git a/Bar.qml b/Bar.qml index 557a746..77c92a9 100644 --- a/Bar.qml +++ b/Bar.qml @@ -26,9 +26,17 @@ Scope { screen: modelData mask: Region { + Region { + item: left + } + Region { item: center } + + Region { + item: right + } } anchors { @@ -46,12 +54,20 @@ Scope { RowLayout { anchors { left: parent.left + leftMargin: 3 right: parent.right + rightMargin: 3 top: parent.top } Row { id: left + + Layout.alignment: Qt.AlignTop + + WorkspaceSelector { + monitor: win.monitor + } } Item { @@ -61,6 +77,8 @@ Scope { Row { id: center + Layout.alignment: Qt.AlignTop + Time { monitor: win.monitor } @@ -72,6 +90,8 @@ Scope { Row { id: right + + Layout.alignment: Qt.AlignTop } } } diff --git a/Bar/WorkspaceSelector.qml b/Bar/WorkspaceSelector.qml new file mode 100644 index 0000000..99e7469 --- /dev/null +++ b/Bar/WorkspaceSelector.qml @@ -0,0 +1,43 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + required property HyprlandMonitor monitor + + boxHeight: 25 + exclusiveMonitor: monitor + + Row { + spacing: 3 + + Repeater { + delegate: workspaceButton + model: WorkspaceManager.getWorkspacesForMonitor(root.exclusiveMonitor) + delegateModelAccess: DelegateModel.ReadOnly + } + + Component { + id: workspaceButton + + Item { + required property var modelData + + height: 10 + width: 10 + + Rectangle { + anchors.fill: parent + color: "red" + } + } + } + } +} From abe1a1e12f668bfcf26a27963a06c2d1e2d6ea96 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 14:09:14 +0100 Subject: [PATCH 04/38] functional workspace display --- Bar/WorkspaceSelector.qml | 45 ++++++++++++++++++++++++++++------- Services/WorkspaceManager.qml | 11 +++++++++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Bar/WorkspaceSelector.qml b/Bar/WorkspaceSelector.qml index 99e7469..4018817 100644 --- a/Bar/WorkspaceSelector.qml +++ b/Bar/WorkspaceSelector.qml @@ -1,5 +1,6 @@ +pragma ComponentBehavior: Bound import QtQuick -import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Hyprland @@ -10,32 +11,58 @@ import "../Services/" Container { id: root + property double barHeight: 25 required property HyprlandMonitor monitor + property double rowLeftMargin: 5 + property double workspaceButtonSpacing: 4 + property double workspaceCount: WorkspaceManager.getNumberOfWorkspaces(monitor) + property double workspaceWidth: 17 - boxHeight: 25 + boxHeight: barHeight + boxRadius: 8 + boxWidth: (2 * rowLeftMargin) + (workspaceCount * workspaceWidth) + ((workspaceCount - 1) + * workspaceButtonSpacing) exclusiveMonitor: monitor - Row { - spacing: 3 + RowLayout { + spacing: root.workspaceButtonSpacing + + anchors { + bottom: parent.bottom + left: parent.left + leftMargin: root.rowLeftMargin + top: parent.top + } Repeater { delegate: workspaceButton + delegateModelAccess: DelegateModel.ReadOnly model: WorkspaceManager.getWorkspacesForMonitor(root.exclusiveMonitor) - delegateModelAccess: DelegateModel.ReadOnly } Component { id: workspaceButton Item { - required property var modelData + id: buttonRoot - height: 10 - width: 10 + required property var modelData + property double stateInt: WorkspaceManager.getWorkspaceStateIndex(modelData) + property variant workspaceColors: [Colors.lavender, Colors.overlay2, Colors.surface2] + property string workspaceId: modelData.id + + Layout.alignment: Qt.AlignLeft + height: root.barHeight - 7 + implicitWidth: root.workspaceWidth Rectangle { anchors.fill: parent - color: "red" + color: buttonRoot.workspaceColors[buttonRoot.stateInt] + radius: 4 + + CenteredText { + text: buttonRoot.modelData.id + } } } } diff --git a/Services/WorkspaceManager.qml b/Services/WorkspaceManager.qml index d238bc9..8b1c685 100644 --- a/Services/WorkspaceManager.qml +++ b/Services/WorkspaceManager.qml @@ -62,6 +62,17 @@ Singleton { } } + function getWorkspaceStateIndex(workspace) { + let state = getWorkspaceState(workspace); + if (state == "focused") { + return 0; + } else if (state == "active") { + return 1; + } else if (state == "inactive") { + return 2; + } + } + function getWorkspacesForMonitor(monitor) { let allWorkspaces = getAllNumberedWorkspaces(); let monitorWorkspaces = []; From 89ee2ec974000a532ede2d4ccd57c02858ec23d3 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 14:14:58 +0100 Subject: [PATCH 05/38] now can press the workspace to switch to it --- Bar/WorkspaceSelector.qml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Bar/WorkspaceSelector.qml b/Bar/WorkspaceSelector.qml index 4018817..1b56038 100644 --- a/Bar/WorkspaceSelector.qml +++ b/Bar/WorkspaceSelector.qml @@ -24,6 +24,18 @@ Container { * workspaceButtonSpacing) exclusiveMonitor: monitor + states: [ + State { + name: "hovered" + when: root.hovered + + PropertyChanges { + root.barHeight: 30 + root.workspaceWidth: 25 + } + } + ] + RowLayout { spacing: root.workspaceButtonSpacing @@ -55,6 +67,12 @@ Container { height: root.barHeight - 7 implicitWidth: root.workspaceWidth + TapHandler { + id: tapHandler + + onTapped: WorkspaceManager.activateWorkspaceById(buttonRoot.modelData.id) + } + Rectangle { anchors.fill: parent color: buttonRoot.workspaceColors[buttonRoot.stateInt] From bc2f308673ccf5bee9bac5a34d823c4f6ae0c090 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 17:43:27 +0100 Subject: [PATCH 06/38] changed width --- Bar/Time.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bar/Time.qml b/Bar/Time.qml index dbb3ba5..777a090 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -24,7 +24,7 @@ Container { PropertyChanges { root.boxHeight: 32 root.boxRadius: 12 - root.boxWidth: 110 + root.boxWidth: 107 } } ] From 185e7618a4293a7ea55d695340e15f26d48a6576 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 17:43:44 +0100 Subject: [PATCH 07/38] fixed weird layout thing --- Bar.qml | 65 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/Bar.qml b/Bar.qml index 77c92a9..60a9880 100644 --- a/Bar.qml +++ b/Bar.qml @@ -51,47 +51,52 @@ Scope { topMargin: 3 } - RowLayout { + anchors { + left: parent.left + leftMargin: 3 + right: parent.right + rightMargin: 3 + top: parent.top + } + + Row { + id: left + anchors { left: parent.left - leftMargin: 3 - right: parent.right - rightMargin: 3 top: parent.top } - Row { - id: left + WorkspaceSelector { + monitor: win.monitor + } + } - Layout.alignment: Qt.AlignTop + Row { + id: center - WorkspaceSelector { - monitor: win.monitor - } + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top } - Item { - Layout.fillWidth: true + Time { + monitor: win.monitor + } + } + + Row { + id: right + + Layout.alignment: Qt.AlignTop + + anchors { + right: parent.right + top: parent.top } - Row { - id: center - - Layout.alignment: Qt.AlignTop - - Time { - monitor: win.monitor - } - } - - Item { - Layout.fillWidth: true - } - - Row { - id: right - - Layout.alignment: Qt.AlignTop + Bluetooth { + monitor: win.monitor } } } From 78f92f1dbf242ab6d7c7b6f1cbeeb4ffae9a0a58 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 17:43:50 +0100 Subject: [PATCH 08/38] fixed "nothing to push error" --- Bar/WorkspaceSelector.qml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Bar/WorkspaceSelector.qml b/Bar/WorkspaceSelector.qml index 1b56038..042e365 100644 --- a/Bar/WorkspaceSelector.qml +++ b/Bar/WorkspaceSelector.qml @@ -22,6 +22,7 @@ Container { boxRadius: 8 boxWidth: (2 * rowLeftMargin) + (workspaceCount * workspaceWidth) + ((workspaceCount - 1) * workspaceButtonSpacing) + defaultItem: placeholder exclusiveMonitor: monitor states: [ @@ -31,11 +32,17 @@ Container { PropertyChanges { root.barHeight: 30 - root.workspaceWidth: 25 + root.workspaceWidth: 20 } } ] + Component { + id: placeholder + + Item {} + } + RowLayout { spacing: root.workspaceButtonSpacing @@ -64,9 +71,22 @@ Container { property string workspaceId: modelData.id Layout.alignment: Qt.AlignLeft - height: root.barHeight - 7 + implicitHeight: root.barHeight - 7 implicitWidth: root.workspaceWidth + Behavior on implicitHeight { + SpringAnimation { + damping: 0.3 + spring: 4 + } + } + Behavior on implicitWidth { + SpringAnimation { + damping: 0.3 + spring: 4 + } + } + TapHandler { id: tapHandler From 4ef5f39f6d25dd3bd3cd6717bb2c365d8328b55b Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 17:44:10 +0100 Subject: [PATCH 09/38] added propo option to StyledText --- Components/StyledText.qml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Components/StyledText.qml b/Components/StyledText.qml index 4da4ce9..d20bbe7 100644 --- a/Components/StyledText.qml +++ b/Components/StyledText.qml @@ -2,12 +2,17 @@ import QtQuick import "../Color.js" as Colors Text { + id: root + + property double fontSize: 12 + property bool propo: false + color: Colors.base elide: Text.ElideRight font { - family: "FiraMono Nerd Font" - pointSize: 12 + family: root.propo == true ? "FiraMono Nerd Font Propo" : "FiraMono Nerd Font" + pointSize: fontSize weight: 800 } } From 7cceb3a91a9ab65b271a8b4eb030c908aa365aa2 Mon Sep 17 00:00:00 2001 From: voidarc Date: Thu, 6 Aug 2026 17:44:23 +0100 Subject: [PATCH 10/38] functional bluetooth module --- Bar/Bluetooth.qml | 109 ++++++++++++++++++++++++++++++++++ Services/BluetoothManager.qml | 36 ++++------- 2 files changed, 120 insertions(+), 25 deletions(-) create mode 100644 Bar/Bluetooth.qml diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml new file mode 100644 index 0000000..e0e0b7e --- /dev/null +++ b/Bar/Bluetooth.qml @@ -0,0 +1,109 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + required property HyprlandMonitor monitor + property bool opened: false + + animOffset: 200 + boxColor: Colors.peach + boxHeight: 25 + boxWidth: 33 + defaultItem: icon + exclusiveMonitor: root.monitor + exclusiveToScreen: true + forceHidden: !(BluetoothManager.getConnected()) + + states: [ + State { + name: "hovered" + when: root.hovered == true && root.opened == false + + PropertyChanges { + root.boxHeight: 28 + root.boxWidth: 35 + } + }, + State { + name: "opened" + when: root.opened == true && root.hovered == true + + PropertyChanges { + root.boxHeight: 300 + root.boxWidth: 350 + } + + StateChangeScript { + script: { + stack.replace(deviceList); + } + } + } + ] + + hover.onHoveredChanged: { + if (hover.hovered == false) { + root.opened = false; + if (root.state != "icon") { + root.stack.replace(icon); + } + } + } + tap.onTapped: { + root.opened = true; + } + + Component { + id: icon + + StyledText { + property string component: "icon" + + horizontalAlignment: Qt.AlignCenter + propo: true + text: "󰂱" + verticalAlignment: Qt.AlignVCenter + } + } + + Component { + id: deviceList + + Column { + property string component: "deviceList" + + spacing: 3 + + Repeater { + delegate: devicePlaque + model: BluetoothManager.getConnectedDevicesList() + } + + Component { + id: devicePlaque + + Rectangle { + id: devicePlaqueRoot + + required property var modelData + + color: Colors.surface1 + implicitHeight: 10 + + anchors { + left: parent.left + right: parent.right + } + } + } + } + } +} diff --git a/Services/BluetoothManager.qml b/Services/BluetoothManager.qml index 41f8a1d..ed23df7 100644 --- a/Services/BluetoothManager.qml +++ b/Services/BluetoothManager.qml @@ -20,6 +20,17 @@ Singleton { return false; } + function getConnectedDevicesList() { + let devicesList = getDevicesList(); + let connectedList = []; + for (let device of devicesList) { + if (device.connected == true) { + connectedList.push(device); + } + } + return connectedList; + } + function getDevicesList() { return root.defaultAdapter.devices.values; } @@ -41,29 +52,4 @@ Singleton { return icons[name] || "󰾰"; } - - function pairTrustConnect(device) { - device.pair(); - device.trusted = true; - device.connect(); - } - - function toggleDiscover() { - if (defaultAdapter.discovering == true) { - defaultAdapter.discovering = false; - } else { - defaultAdapter.discovering = true; - discoveringTimeout.running = true; - } - } - - Timer { - id: discoveringTimeout - - interval: 15000 - repeat: false - running: false - - onTriggered: defaultAdapter.discovering = false - } } From 11a8f032152d2d225942e75634e4a0b4be5dc609 Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 14:49:49 +0100 Subject: [PATCH 11/38] bluetooth menu coming along --- Bar/Bluetooth.qml | 50 ++++++++++++++++++++++++++++++++--- Services/BluetoothManager.qml | 11 ++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index e0e0b7e..42c45b4 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -1,3 +1,4 @@ +pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell @@ -10,6 +11,8 @@ import "../Services/" Container { id: root + property double devicePlaqeuSpacing + property double devicePlaqueHeight required property HyprlandMonitor monitor property bool opened: false @@ -38,6 +41,7 @@ Container { PropertyChanges { root.boxHeight: 300 + root.boxRadius: 12 root.boxWidth: 350 } @@ -78,9 +82,18 @@ Container { id: deviceList Column { - property string component: "deviceList" + id: deviceListRoot - spacing: 3 + property string component: "deviceList" + property double plaqueHeight: 60 + property double plaqueSpacing: 4 + + spacing: plaqueSpacing + + Item { + implicitHeight: 1 + implicitWidth: 10 + } Repeater { delegate: devicePlaque @@ -93,14 +106,45 @@ Container { Rectangle { id: devicePlaqueRoot + readonly property variant deviceText: BluetoothManager.getDeviceText(modelData) + readonly property double margin: 5 required property var modelData color: Colors.surface1 - implicitHeight: 10 + implicitHeight: deviceListRoot.plaqueHeight + radius: 10 anchors { left: parent.left + leftMargin: devicePlaqueRoot.margin right: parent.right + rightMargin: devicePlaqueRoot.margin + } + + Item { + anchors.fill: parent + + Rectangle { + id: iconContainer + + property double margin: 7 + + color: Colors.text + implicitWidth: deviceListRoot.plaqueHeight - (margin * 2) + radius: 4 + + anchors { + bottom: parent.bottom + left: parent.left + margins: iconContainer.margin + top: parent.top + } + + CenteredText { + fontSize: 17 + text: devicePlaqueRoot.deviceText["icon"] + } + } } } } diff --git a/Services/BluetoothManager.qml b/Services/BluetoothManager.qml index ed23df7..6805eb4 100644 --- a/Services/BluetoothManager.qml +++ b/Services/BluetoothManager.qml @@ -31,6 +31,17 @@ Singleton { return connectedList; } + function getDeviceText(device) { + let deviceName = device.deviceName; + + let deviceIcon = getIcon(device.icon); + + return { + "icon": deviceIcon, + "name": deviceName + }; + } + function getDevicesList() { return root.defaultAdapter.devices.values; } From d54487022fcd2323f4a04c5ca55fc20508d87b6a Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 16:18:17 +0100 Subject: [PATCH 12/38] made panelwindow apply to the whole bar instead of individual containers --- Bar.qml | 152 +++++++++++++++++++++++---------------- Components/Container.qml | 10 --- 2 files changed, 89 insertions(+), 73 deletions(-) diff --git a/Bar.qml b/Bar.qml index 60a9880..73732a0 100644 --- a/Bar.qml +++ b/Bar.qml @@ -8,96 +8,122 @@ import "Color.js" as Colors Scope { Variants { + id: panelDelegate + + delegate: panelWindow model: Quickshell.screens + } - delegate: Component { - PanelWindow { - id: win + Component { + id: panelWindow - property double barExclusionZone: 15 - property double barMaxHeight: 1000 - required property var modelData - property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) + PanelWindow { + id: win - color: "transparent" - exclusionMode: ExclusionMode.Normal - exclusiveZone: barExclusionZone - implicitHeight: barMaxHeight - screen: modelData + property double barExclusionZone: 15 + property double barMaxHeight: 1000 + required property var modelData + property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) - mask: Region { - Region { - item: left - } + color: "transparent" + exclusionMode: ExclusionMode.Normal + exclusiveZone: barExclusionZone + implicitHeight: barMaxHeight + mask: maskRegion + screen: modelData - Region { - item: center - } + Region { + id: maskRegion - Region { - item: right - } + Region { + item: left + } + + Region { + item: center + } + + Region { + item: right + } + } + + anchors { + left: true + right: true + top: true + } + + MultiEffect { + anchors.fill: rowContainer + shadowBlur: 1.5 + shadowColor: Colors.mantle + shadowEnabled: true + shadowHorizontalOffset: 5 + shadowOpacity: 1 + shadowVerticalOffset: 3 + source: rowContainer + } + + Item { + id: rowContainer + + anchors { + fill: parent + topMargin: 3 } anchors { - left: true - right: true - top: true + left: parent.left + leftMargin: 3 + right: parent.right + rightMargin: 3 + top: parent.top } - Item { - anchors { - fill: parent - topMargin: 3 - } + Row { + id: left anchors { left: parent.left - leftMargin: 3 - right: parent.right - rightMargin: 3 top: parent.top } - Row { - id: left + WorkspaceSelector { + monitor: win.monitor + } + } - anchors { - left: parent.left - top: parent.top - } + Row { + id: center - WorkspaceSelector { - monitor: win.monitor - } + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top } - Row { - id: center + Time { + monitor: win.monitor + } + } - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.top - } + Row { + id: right - Time { - monitor: win.monitor - } + Layout.alignment: Qt.AlignTop + spacing: 5 + + anchors { + right: parent.right + top: parent.top } - Row { - id: right + Network { + monitor: win.monitor + } - Layout.alignment: Qt.AlignTop - - anchors { - right: parent.right - top: parent.top - } - - Bluetooth { - monitor: win.monitor - } + Bluetooth { + monitor: win.monitor } } } diff --git a/Components/Container.qml b/Components/Container.qml index a178d59..988b76d 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -94,16 +94,6 @@ Item { id: tapHandler } - RectangularShadow { - anchors.fill: container - blur: 30 - color: Colors.mantle - offset.x: 5 - offset.y: 2 - radius: container.radius - spread: 5 - } - Rectangle { id: container From 6f3e62bcf938cbfcd9658ec3c17416599be663bd Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 16:18:24 +0100 Subject: [PATCH 13/38] added networkmanager --- Services/NetworkManager.qml | 27 +++++++++++++++++++++++++++ Services/qmldir | 1 + 2 files changed, 28 insertions(+) create mode 100644 Services/NetworkManager.qml diff --git a/Services/NetworkManager.qml b/Services/NetworkManager.qml new file mode 100644 index 0000000..6fc0c54 --- /dev/null +++ b/Services/NetworkManager.qml @@ -0,0 +1,27 @@ +pragma Singleton +import QtQuick +import Quickshell +import Quickshell.Networking + +Singleton { + id: root + + property NetworkDevice defaultAdapter: Networking.devices.values[0] + + function getConnectivity() { + if (Networking.connectivity == NetworkConnectivity.Full) { + return 0; + // if ethernet hide ts (return 2) + } else if (Networking.connectivity == NetworkConnectivity.Limited || Networking.connectivity + == NetworkConnectivity.Portal) { + return 1; + } else { + return 2; + } + } + + function getIcon() { + let state = getConnectivity(); + let iconArr = [""]; + } +} diff --git a/Services/qmldir b/Services/qmldir index 6e2dbe3..54e051b 100644 --- a/Services/qmldir +++ b/Services/qmldir @@ -5,3 +5,4 @@ singleton WorkspaceManager 1.0 WorkspaceManager.qml singleton BluetoothManager 1.0 BluetoothManager.qml singleton MprisManager 1.0 MprisManager.qml singleton BatteryManager 1.0 BatteryManager.qml +singleton NetworkManager 1.0 NetworkManager.qml From 8267743fb522d20d3bae73b6daaa4683a5836b08 Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 17:14:38 +0100 Subject: [PATCH 14/38] bluetooth donesies i think --- Bar/Bluetooth.qml | 69 ++++++++++++++++++++++++++++++----- Services/BluetoothManager.qml | 15 +++++++- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index 42c45b4..b89d6a1 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -121,30 +121,79 @@ Container { rightMargin: devicePlaqueRoot.margin } - Item { - anchors.fill: parent + RowLayout { + id: deviceInfoRow + + property double margin: 7 + + spacing: margin * 2 + + anchors { + fill: parent + leftMargin: margin + } Rectangle { id: iconContainer - property double margin: 7 + property double boxRadius: 4 color: Colors.text - implicitWidth: deviceListRoot.plaqueHeight - (margin * 2) - radius: 4 + implicitHeight: deviceListRoot.plaqueHeight - (deviceInfoRow.margin * 2) + implicitWidth: deviceListRoot.plaqueHeight - (deviceInfoRow.margin * 2) + radius: boxRadius - anchors { - bottom: parent.bottom - left: parent.left - margins: iconContainer.margin - top: parent.top + Rectangle { + id: batteryIndicator + + color: Colors.green + implicitHeight: (deviceListRoot.plaqueHeight - (deviceInfoRow.margin * 2)) + * devicePlaqueRoot.deviceText["batteryRaw"] + radius: iconContainer.boxRadius + + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } + + HoverHandler { + id: batteryHoverHandler + + onHoveredChanged: { + if (batteryHoverHandler.hovered == true) { + batteryText.text = devicePlaqueRoot.deviceText["battery"]; + } else { + batteryText.text = devicePlaqueRoot.deviceText["icon"]; + } + } } CenteredText { + id: batteryText + fontSize: 17 text: devicePlaqueRoot.deviceText["icon"] } } + + Column { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + + StyledText { + color: Colors.text + fontSize: 14 + text: devicePlaqueRoot.deviceText["name"] + } + + StyledText { + color: Colors.subtext1 + fontSize: 10 + text: devicePlaqueRoot.deviceText["mac"] + } + } } } } diff --git a/Services/BluetoothManager.qml b/Services/BluetoothManager.qml index 6805eb4..f3c268c 100644 --- a/Services/BluetoothManager.qml +++ b/Services/BluetoothManager.qml @@ -33,12 +33,23 @@ Singleton { function getDeviceText(device) { let deviceName = device.deviceName; - let deviceIcon = getIcon(device.icon); + let deviceMac = device.address; + let hasBattery = device.batteryAvailable; + let deviceBattery = deviceIcon; + let deviceBatteryRaw = 0; + if (hasBattery) { + deviceBattery = device.battery * 100; + deviceBatteryRaw = device.battery; + } return { "icon": deviceIcon, - "name": deviceName + "name": deviceName, + "mac": deviceMac, + "hasBattery": hasBattery, + "battery": deviceBattery, + "batteryRaw": deviceBatteryRaw }; } From 942b17957293117ee5c63894640c2a2b48545100 Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 18:25:37 +0100 Subject: [PATCH 15/38] added closed state to stop weird sizing behavior --- Bar/Bluetooth.qml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index b89d6a1..2c341e0 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -26,6 +26,16 @@ Container { forceHidden: !(BluetoothManager.getConnected()) states: [ + State { + name: "closed" + when: root.hovered == false && root.opened == false + + PropertyChanges { + root.boxHeight: 25 + root.boxRadius: 9 + root.boxWidth: 33 + } + }, State { name: "hovered" when: root.hovered == true && root.opened == false From f5623585fbecba82d38eb3aa5a479be492314f95 Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 18:25:46 +0100 Subject: [PATCH 16/38] network finished --- Bar/Network.qml | 96 +++++++++++++++++++++++++++++++++++++ Services/NetworkManager.qml | 74 +++++++++++++++++++++++----- 2 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 Bar/Network.qml diff --git a/Bar/Network.qml b/Bar/Network.qml new file mode 100644 index 0000000..ddec3cf --- /dev/null +++ b/Bar/Network.qml @@ -0,0 +1,96 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + required property HyprlandMonitor monitor + property bool opened: false + + boxColor: Colors.red + boxHeight: 25 + boxWidth: 33 + defaultItem: icon + exclusiveMonitor: root.monitor + exclusiveToScreen: true + forceHidden: !NetworkManager.isConnectedAndWifi() + + states: [ + State { + name: "closed" + when: root.hovered == false && root.opened == false + + PropertyChanges { + root.boxHeight: 25 + root.boxRadius: 9 + root.boxWidth: 33 + } + }, + State { + name: "hovered" + when: root.hovered == true && root.opened == false + + PropertyChanges { + root.boxHeight: 28 + root.boxWidth: 35 + } + }, + State { + name: "opened" + when: root.opened == true && root.hovered == true + + PropertyChanges { + root.boxHeight: 28 + root.boxRadius: 12 + root.boxWidth: 350 + } + + StateChangeScript { + script: { + stack.replace(wifiInfo); + } + } + } + ] + + hover.onHoveredChanged: { + if (hover.hovered == false) { + root.opened = false; + if (root.state != "icon") { + root.stack.replace(icon); + } + } + } + tap.onTapped: { + root.opened = true; + } + + Component { + id: icon + + StyledText { + horizontalAlignment: Qt.AlignCenter + propo: true + text: NetworkManager.getNetworkDetails(NetworkManager.defaultAdapter)["icon"] + verticalAlignment: Qt.AlignVCenter + } + } + + Component { + id: wifiInfo + + StyledText { + horizontalAlignment: Qt.AlignCenter + propo: true + text: NetworkManager.getWifiText() + verticalAlignment: Qt.AlignVCenter + } + } +} diff --git a/Services/NetworkManager.qml b/Services/NetworkManager.qml index 6fc0c54..8ac51b1 100644 --- a/Services/NetworkManager.qml +++ b/Services/NetworkManager.qml @@ -8,20 +8,70 @@ Singleton { property NetworkDevice defaultAdapter: Networking.devices.values[0] - function getConnectivity() { - if (Networking.connectivity == NetworkConnectivity.Full) { - return 0; - // if ethernet hide ts (return 2) - } else if (Networking.connectivity == NetworkConnectivity.Limited || Networking.connectivity - == NetworkConnectivity.Portal) { - return 1; - } else { - return 2; + function getConnectedNetworks(networksArr) { + let connectedNetworks = []; + + for (let network of networksArr) { + if (network.state == ConnectionState.Connected) { + connectedNetworks.push(network); + } } + return connectedNetworks; } - function getIcon() { - let state = getConnectivity(); - let iconArr = [""]; + function getNetworkDetails(adapter) { + let networksArr = adapter.networks.values; + let connectedNetworks = getConnectedNetworks(networksArr); + let deviceWifi = isDeviceWifi(adapter); + + let primaryNetwork = connectedNetworks[0]; + + let networkName = primaryNetwork.name; + let networkStrength = primaryNetwork.signalStrength; + + let networkIcon = getWifiIcon(networkStrength); + + let outputDict = { + "adapterName": adapter.name, + "adapterConnected": adapter.connected, + "adapterIsWifi": deviceWifi, + "networkName": networkName, + "networkStrength": networkStrength, + "icon": networkIcon + }; + return outputDict; + } + + function getWifiIcon(strength) { + let iconArr = ["󰤟", "󰤢", "󰤥", "󰤨"]; + let strengthIndex = Math.ceil(strength * iconArr.length); + return iconArr[strengthIndex - 1]; + } + + function isConnectedAndWifi() { + let isConnected = defaultAdapter.connected + let isWifi = isDeviceWifi(defaultAdapter) + return isConnected && isWifi + } + + function getWifiText() { + let info = getNetworkDetails(defaultAdapter); + + let adapter = info["adapterName"]; + let name = info["networkName"]; + + let finalString = adapter + " - " + name; + return finalString; + } + + function isDeviceWifi(adapter) { + if (adapter.type == DeviceType.Wifi) { + return true; + } else if (adapter.type == DeviceType.Wired) { + return false; + } else { + console.log(adapter.type); + return false; + } } } From ce5bbb1dff02db86e1b1b38364f08e469dd93bf2 Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 20:31:47 +0100 Subject: [PATCH 17/38] fixed bluetooth height --- Bar/Bluetooth.qml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index 2c341e0..9c8bff1 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -11,8 +11,8 @@ import "../Services/" Container { id: root - property double devicePlaqeuSpacing - property double devicePlaqueHeight + property double devicePlaqueHeight: 60 + property double devicePlaqueSpacing: 4 required property HyprlandMonitor monitor property bool opened: false @@ -50,7 +50,8 @@ Container { when: root.opened == true && root.hovered == true PropertyChanges { - root.boxHeight: 300 + root.boxHeight: (root.devicePlaqueHeight * BluetoothManager.getConnectedDevicesList().length) + ( + root.devicePlaqueSpacing * (BluetoothManager.getConnectedDevicesList().length + 1)) root.boxRadius: 12 root.boxWidth: 350 } @@ -95,8 +96,8 @@ Container { id: deviceListRoot property string component: "deviceList" - property double plaqueHeight: 60 - property double plaqueSpacing: 4 + property double plaqueHeight: root.devicePlaqueHeight + property double plaqueSpacing: root.devicePlaqueSpacing spacing: plaqueSpacing From 01fdddf0e883dbd8290e5f90f39b1e49765d4bec Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 20:31:56 +0100 Subject: [PATCH 18/38] made gradient rotatable --- Components/MidpointGradient.qml | 76 +++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/Components/MidpointGradient.qml b/Components/MidpointGradient.qml index 333c5fd..43fdb76 100644 --- a/Components/MidpointGradient.qml +++ b/Components/MidpointGradient.qml @@ -1,23 +1,75 @@ import QtQuick +import QtQuick.Shapes -Gradient { +Item { id: root - required property color color - property double midpoint: 0.6 + property real angle: 0 // Degrees; 0 = transparent left, colour right + readonly property real angleRadians: angle * Math.PI / 180.0 + property real blur: 0.0 // 0 = sharp, 1 = very soft - GradientStop { - color: "transparent" - position: 0.0 + // Public API + property color color: "#4da3ffff" + + // Half the diagonal ensures the gradient covers the entire item. + readonly property real gradientRadius: Math.sqrt(width * width + height * height) / 2.0 + property real midpoint: 0.5 // 0..1 + property double radius: 10 + readonly property real safeBlur: Math.max(blur, 0.00001) + readonly property real safeMidpoint: clamp01(midpoint) + readonly property real transitionEnd: clamp01(safeMidpoint + safeBlur / 2.0) + readonly property real transitionStart: clamp01(safeMidpoint - safeBlur / 2.0) + readonly property color transparentColor: Qt.rgba(color.r, color.g, color.b, 0.0) + + function clamp01(value) { + return Math.max(0.0, Math.min(1.0, value)); } - GradientStop { - color: "transparent" - position: root.midpoint + Behavior on color { + ColorAnimation { + duration: 100 + } } - GradientStop { - color: root.color - position: 1.0 + Shape { + anchors.fill: parent + preferredRendererType: Shape.CurveRenderer + + ShapePath { + strokeWidth: -1 + + fillGradient: LinearGradient { + x1: root.width / 2.0 - root.gradientRadius * Math.cos(root.angleRadians) + x2: root.width / 2.0 + root.gradientRadius * Math.cos(root.angleRadians) + y1: root.height / 2.0 - root.gradientRadius * Math.sin(root.angleRadians) + y2: root.height / 2.0 + root.gradientRadius * Math.sin(root.angleRadians) + + GradientStop { + color: root.transparentColor + position: 0.0 + } + + GradientStop { + color: root.transparentColor + position: root.transitionStart + } + + GradientStop { + color: root.color + position: root.transitionEnd + } + + GradientStop { + color: root.color + position: 1.0 + } + } + + PathRectangle { + height: root.height + radius: Math.min(root.radius, Math.min(width, height) / 2.0) + width: root.width + } + } } } From d0e1e2170c6429dfc262065c76dec7a5f5df57fe Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 20:32:01 +0100 Subject: [PATCH 19/38] battery things --- Bar.qml | 4 + Bar/Battery.qml | 173 ++++++++++++++++++++++++++++++++++++ Services/BatteryManager.qml | 85 +++++++++++++++--- 3 files changed, 252 insertions(+), 10 deletions(-) create mode 100644 Bar/Battery.qml diff --git a/Bar.qml b/Bar.qml index 73732a0..70f972d 100644 --- a/Bar.qml +++ b/Bar.qml @@ -125,6 +125,10 @@ Scope { Bluetooth { monitor: win.monitor } + + Battery { + monitor: win.monitor + } } } } diff --git a/Bar/Battery.qml b/Bar/Battery.qml new file mode 100644 index 0000000..2c344aa --- /dev/null +++ b/Bar/Battery.qml @@ -0,0 +1,173 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + property double batteryDisplayHeight: 100 + required property HyprlandMonitor monitor + property bool opened: false + property double radius: 9 + + boxColor: Colors.green + boxHeight: 25 + boxRadius: radius + boxWidth: 55 + defaultItem: icon + exclusiveMonitor: root.monitor + + states: [ + State { + name: "closed" + when: root.hovered == false && root.opened == false + + PropertyChanges { + root.boxHeight: 25 + root.boxRadius: 9 + root.boxWidth: 55 + } + }, + State { + name: "hovered" + when: root.hovered == true && root.opened == false + + PropertyChanges { + root.boxHeight: 28 + root.boxWidth: 60 + } + }, + State { + name: "opened" + when: root.opened == true && root.hovered == true + + PropertyChanges { + root.boxHeight: root.batteryDisplayHeight + root.boxRadius: 12 + root.boxWidth: 350 + } + + StateChangeScript { + script: { + stack.replace(batteryDisplay); + } + } + } + ] + + hover.onHoveredChanged: { + if (hover.hovered == false) { + root.opened = false; + if (root.state != "icon") { + root.stack.replace(icon); + } + } + } + tap.onTapped: { + root.opened = true; + } + + Component { + id: icon + + Item { + MidpointGradient { + anchors.fill: parent + angle: -45 + blur: 0.6 + color: BatteryManager.getBatteryColor() + midpoint: 0.55 + radius: radius + } + + CenteredText { + property string component: "icon" + + propo: true + text: BatteryManager.getBatteryText() + } + } + } + + Component { + id: batteryDisplay + + Item { + id: batteryDisplayRoot + + property double innerMargin: 5 + property double outerMargin: 6 + + Rectangle { + id: batteryBackground + + anchors.fill: parent + anchors.margins: batteryDisplayRoot.outerMargin + color: Colors.surface1 + radius: 8 + + RowLayout { + anchors.fill: parent + + Rectangle { + id: percentBox + + property double percentBoxRadius: 5 + + Layout.fillHeight: true + Layout.margins: batteryDisplayRoot.innerMargin + color: Colors.text + implicitWidth: root.batteryDisplayHeight - (batteryDisplayRoot.innerMargin * 2) - ( + batteryDisplayRoot.outerMargin * 2) + radius: 5 + + Rectangle { + color: Colors.green + implicitHeight: (root.batteryDisplayHeight - (batteryDisplayRoot.innerMargin * 2) - ( + batteryDisplayRoot.outerMargin * 2)) * BatteryManager.mainBattery.percentage + radius: percentBox.percentBoxRadius + + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } + + CenteredText { + fontSize: 15 + text: BatteryManager.getBatteryPercentage(BatteryManager.mainBattery) + "%" + } + } + + Column { + id: batColumn + + property var batInfo: BatteryManager.getMainBatteryInfo() + + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + + StyledText { + color: Colors.text + fontSize: 13 + text: "Battery - " + batColumn.batInfo["name"] + } + + StyledText { + color: Colors.text + fontSize: 13 + text: batColumn.batInfo["energy"] + " / " + batColumn.batInfo["capacity"] + "Wh" + } + } + } + } + } + } +} diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index c99c28c..50810e8 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -3,21 +3,86 @@ import QtQuick import Quickshell import Quickshell.Services.UPower +import "../Color.js" as Colors + Singleton { id: root - property UPowerDevice battery: Upower.displayDevice property bool batteryInUse: root.batteryPresent && root.batteryLaptop - property bool batteryLaptop: root.battery.isLaptopBattery - property double batteryPercentage: root.battery.percentage - property bool batteryPresent: root.battery.ready + property bool batteryLaptop: root.mainBattery.isLaptopBattery + property double batteryPercentage: root.mainBattery.percentage + property bool batteryPresent: root.mainBattery.ready + property UPowerDevice mainBattery: UPower.displayDevice - function getBatteryIcon() { - let battery = root.battery; - if (battery.state = UpowerDeviceState.Charging) { - return "󰂄"; - } - if (battery.state = UpowerDeviceState.Discharging) { + function getBatteryColor() { + let criticalLevel = 20; + let batteryPercentage = getBatteryPercentage(mainBattery); + + if (mainBattery.state == UPowerDeviceState.Charging) { + return Colors.mauve; + } else if (mainBattery.state == UPowerDeviceState.PendingCharge | mainBattery.state + == UPowerDeviceState.PendingDischarge) { + return Colors.peach; + } else if (batteryPercentage <= criticalLevel) { + return Colors.red; + } else { + return Colors.green; } } + + function getBatteryIcon(battery) { + if (battery.state == UPowerDeviceState.Charging) { + return "󰂄"; + } else if (battery.state == UPowerDeviceState.PendingCharge | battery.state + == UPowerDeviceState.PendingDischarge) { + return "󰚥"; + } else if (battery.state == UPowerDeviceState.Discharging | battery.state + == UPowerDeviceState.FullyCharged) { + let iconArr = ["󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"]; + let batteryCharge = battery.percentage; + let chargeIndex = Math.ceil(batteryCharge * iconArr.length) - 1; + return iconArr[chargeIndex]; + } + } + + function getBatteryName(battery) { + let pathsplit = battery.nativePath.split("/"); + let batteryName = pathsplit[pathsplit.length]; + return pathsplit; + } + + function getBatteryPercentage(battery) { + return battery.percentage * 100; + } + + function getBatteryText() { + let icon = getBatteryIcon(mainBattery); + let percentage = getBatteryPercentage(mainBattery); + return icon + " " + percentage + "%"; + } + + function getMainBatteryInfo() { + let battery = UPower.devices.values[0]; + let batteryState = battery.state; + let batteryName = getBatteryName(battery); + let time = 0; + let timeString = ""; + let timeToEmpty = battery.timeToEmpty; + if (timeToEmpty == 0) { + timeString = "full"; + time = battery.timeToFull; + } else { + timeString = "empty"; + time = timeToEmpty; + } + return { + "name": batteryName, + "charge": battery.percentage, + "energy": battery.energy, + "capacity": battery.energyCapacity, + "time": time, + "timeString": timeString, + "health": battery.healthPercentage + }; + } } From cf4db3b8dfad219c3f7a7b4b572894684c715bf2 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 15:22:46 +0100 Subject: [PATCH 20/38] added fontweight property to styledtext --- Components/StyledText.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Components/StyledText.qml b/Components/StyledText.qml index d20bbe7..3618bb4 100644 --- a/Components/StyledText.qml +++ b/Components/StyledText.qml @@ -5,6 +5,7 @@ Text { id: root property double fontSize: 12 + property double fontWeight: 8 property bool propo: false color: Colors.base @@ -13,6 +14,6 @@ Text { font { family: root.propo == true ? "FiraMono Nerd Font Propo" : "FiraMono Nerd Font" pointSize: fontSize - weight: 800 + weight: root.fontWeight * 100 } } From 02e99cca742882463c56a3698239270c28936140 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 15:22:53 +0100 Subject: [PATCH 21/38] battery done looks good to me --- Bar/Battery.qml | 49 ++++++++++------- Services/BatteryManager.qml | 103 ++++++++++++++++++++++++++++++------ 2 files changed, 119 insertions(+), 33 deletions(-) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index 2c344aa..4ef5d99 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -17,9 +17,7 @@ Container { property double radius: 9 boxColor: Colors.green - boxHeight: 25 boxRadius: radius - boxWidth: 55 defaultItem: icon exclusiveMonitor: root.monitor @@ -30,8 +28,8 @@ Container { PropertyChanges { root.boxHeight: 25 - root.boxRadius: 9 - root.boxWidth: 55 + root.boxRadius: root.radius + root.boxWidth: 60 } }, State { @@ -40,7 +38,7 @@ Container { PropertyChanges { root.boxHeight: 28 - root.boxWidth: 60 + root.boxWidth: 64 } }, State { @@ -50,7 +48,7 @@ Container { PropertyChanges { root.boxHeight: root.batteryDisplayHeight root.boxRadius: 12 - root.boxWidth: 350 + root.boxWidth: 450 } StateChangeScript { @@ -77,14 +75,7 @@ Container { id: icon Item { - MidpointGradient { - anchors.fill: parent - angle: -45 - blur: 0.6 - color: BatteryManager.getBatteryColor() - midpoint: 0.55 - radius: radius - } + BatteryGradient {} CenteredText { property string component: "icon" @@ -104,6 +95,8 @@ Container { property double innerMargin: 5 property double outerMargin: 6 + BatteryGradient {} + Rectangle { id: batteryBackground @@ -156,18 +149,38 @@ Container { StyledText { color: Colors.text - fontSize: 13 + fontSize: 14 text: "Battery - " + batColumn.batInfo["name"] } StyledText { - color: Colors.text - fontSize: 13 - text: batColumn.batInfo["energy"] + " / " + batColumn.batInfo["capacity"] + "Wh" + color: Colors.subtext1 + fontSize: 12 + fontWeight: 5 + text: batColumn.batInfo["energy"] + "/" + batColumn.batInfo["capacity"] + "Wh - " + + BatteryManager.getChargingRateFormat() + } + + StyledText { + property var timeInfo: batColumn.batInfo["time"] + + color: Colors.subtext1 + fontSize: 12 + fontWeight: 5 + text: BatteryManager.getTimeFormat() } } } } } } + + component BatteryGradient: MidpointGradient { + anchors.fill: parent + angle: -45 + blur: 0.6 + color: BatteryManager.getBatteryColor() + midpoint: 0.55 + radius: radius + } } diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index 50810e8..90c3665 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -18,7 +18,9 @@ Singleton { let criticalLevel = 20; let batteryPercentage = getBatteryPercentage(mainBattery); - if (mainBattery.state == UPowerDeviceState.Charging) { + if (mainBattery.state == UPowerDeviceState.FullyCharged) { + return Colors.sky; + } else if (mainBattery.state == UPowerDeviceState.Charging) { return Colors.mauve; } else if (mainBattery.state == UPowerDeviceState.PendingCharge | mainBattery.state == UPowerDeviceState.PendingDischarge) { @@ -61,28 +63,99 @@ Singleton { return icon + " " + percentage + "%"; } + function getChargingRateFormat() { + let rate = mainBattery.changeRate.toFixed(1); + + let finalString = "harging at " + rate + "W"; + if (rate == 0) { + finalString = "Battery Idle"; + } else if (rate < 0) { + finalString = "C" + finalString; + } else { + finalString = "Disc" + finalString; + } + return finalString; + } + function getMainBatteryInfo() { let battery = UPower.devices.values[0]; let batteryState = battery.state; let batteryName = getBatteryName(battery); - let time = 0; - let timeString = ""; - let timeToEmpty = battery.timeToEmpty; - if (timeToEmpty == 0) { - timeString = "full"; - time = battery.timeToFull; - } else { - timeString = "empty"; - time = timeToEmpty; - } + let time = getTimeFormat(); return { "name": batteryName, "charge": battery.percentage, - "energy": battery.energy, - "capacity": battery.energyCapacity, - "time": time, - "timeString": timeString, + "energy": battery.energy.toFixed(1), + "capacity": battery.energyCapacity.toFixed(1), "health": battery.healthPercentage }; } + + function getTimeFormat() { + let state = mainBattery.state; + let finalString = ""; + if (state == UPowerDeviceState.FullyCharged) { + finalString += "Battery Full"; + } else if (state == UPowerDeviceState.Charging) { + let time = mainBattery.timeToFull; + if (time == 0) { + return "Getting Time..."; + } else { + let timeArr = secondsToTime(time); + // If more than 1 hour + if (timeArr.hours >= 1 || timeArr.hourNeedsIncrement == 1) { + finalString += timeArr.Hours + " Hours "; + // If minutes not 0 + if (timeArr.minutesRounded > 1) { + finalString += timeArr.minutesRounded + " Minutes"; + } + } else { + finalString += timeArr.minutes + " Minutes "; + finalString += timeArr.seconds + " Seconds"; + } + } + finalString += " Until Full"; + } else if (state == UPowerDeviceState.Discharging) { + let time = mainBattery.timeToEmpty; + if (time == 0) { + return "Getting Time..."; + } else { + let timeArr = secondsToTime(time); + // If more than 1 hour + if (timeArr.hours >= 1 || timeArr.hourNeedsIncrement == 1) { + finalString += timeArr.hours + " Hours "; + // If minutes not 0 + if (timeArr.minutesRounded > 1) { + finalString += timeArr.minutesRounded + " Minutes"; + } + } else { + finalString += timeArr.minutes + " Minutes "; + finalString += timeArr.seconds + " Seconds"; + } + } + finalString += " Remaining"; + } else { + finalString += "Getting Time..."; + } + return finalString; + } + + function secondsToTime(totalSeconds) { + totalSeconds = Math.max(0, Number(totalSeconds)); + + const hours = Math.floor(totalSeconds / 3600); + const minutes = Math.floor((totalSeconds % 3600) / 60); + const seconds = Math.floor(totalSeconds % 60); + + const roundedMinutes = minutes + (seconds >= 30 ? 1 : 0); + const hourNeedsIncrement = roundedMinutes === 60; + + return { + hours, + minutes, + seconds, + minutesRounded: hourNeedsIncrement ? 0 : roundedMinutes, + hourNeedsIncrement + }; + } } From d97a6e0a486e29f2ad1dcd7ee691f2ab57a25404 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 17:08:45 +0100 Subject: [PATCH 22/38] sick ass animation for forceHidden --- Components/Container.qml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Components/Container.qml b/Components/Container.qml index 988b76d..d40109c 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -65,6 +65,46 @@ Item { spring: 4 } } + Behavior on implicitWidth { + SpringAnimation { + damping: 0.3 + spring: 4 + } + } + + onForceHiddenChanged: { + if (root.forceHidden == true) { + hideTimer.restart(); + } else { + root.implicitWidth = root.boxWidth; + root.visible = true; + } + } + + Timer { + id: hideTimer + + interval: 250 + repeat: false + running: false + + onTriggered: { + root.implicitWidth = 0; + subHideTimer.restart(); + } + } + + Timer { + id: subHideTimer + + interval: 200 + repeat: false + running: false + + onTriggered: { + root.visible = false; + } + } anchors { top: parent.top From a90afb3154273c4439ae4b8abee2d600d6f95fdd Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 17:11:02 +0100 Subject: [PATCH 23/38] hide battery icon when no laptop battery present --- Bar/Battery.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index 4ef5d99..3e50ea4 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -20,6 +20,7 @@ Container { boxRadius: radius defaultItem: icon exclusiveMonitor: root.monitor + forceHidden: !BatteryManager.batteryLaptop states: [ State { From 300cb0b2f8e3f07ce3258778b627053575f16f80 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 17:11:17 +0100 Subject: [PATCH 24/38] removed duplicate animation --- Components/Container.qml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Components/Container.qml b/Components/Container.qml index d40109c..08302e5 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -59,12 +59,6 @@ Item { spring: 4 } } - Behavior on boxWidth { - SpringAnimation { - damping: 0.3 - spring: 4 - } - } Behavior on implicitWidth { SpringAnimation { damping: 0.3 From 7858c5b90d0d0e25820fb2acc8efc5c8ef700340 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 19:46:17 +0100 Subject: [PATCH 25/38] fixed bluetooth menu margin --- Bar/Bluetooth.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index 9c8bff1..7542f2d 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -51,7 +51,7 @@ Container { PropertyChanges { root.boxHeight: (root.devicePlaqueHeight * BluetoothManager.getConnectedDevicesList().length) + ( - root.devicePlaqueSpacing * (BluetoothManager.getConnectedDevicesList().length + 1)) + root.devicePlaqueSpacing * (BluetoothManager.getConnectedDevicesList().length + 1)) + 2 root.boxRadius: 12 root.boxWidth: 350 } From e371c9cc7bfe27644454788ca5a73e41d138c52b Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 19:46:45 +0100 Subject: [PATCH 26/38] fixed discharging vs charging thing because the wiki lies about the rate parameter --- Services/BatteryManager.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index 90c3665..b5325eb 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -8,8 +8,6 @@ import "../Color.js" as Colors Singleton { id: root - property bool batteryInUse: root.batteryPresent && root.batteryLaptop - property bool batteryLaptop: root.mainBattery.isLaptopBattery property double batteryPercentage: root.mainBattery.percentage property bool batteryPresent: root.mainBattery.ready property UPowerDevice mainBattery: UPower.displayDevice @@ -69,7 +67,7 @@ Singleton { let finalString = "harging at " + rate + "W"; if (rate == 0) { finalString = "Battery Idle"; - } else if (rate < 0) { + } else if (rate <= 0 || mainBattery.state == UPowerDeviceState.Charging) { finalString = "C" + finalString; } else { finalString = "Disc" + finalString; From b3c46e2df26a5087886d58d6755a29d1a59e6bf0 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 19:58:49 +0100 Subject: [PATCH 27/38] made it rely on laptop battery --- Bar/Battery.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index 3e50ea4..6e13996 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -20,7 +20,7 @@ Container { boxRadius: radius defaultItem: icon exclusiveMonitor: root.monitor - forceHidden: !BatteryManager.batteryLaptop + forceHidden: !BatteryManager.mainBattery.isLaptopBattery states: [ State { From 021ddae2d06580eeae9b284f8607e0ca23c1c9d0 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sat, 8 Aug 2026 19:59:10 +0100 Subject: [PATCH 28/38] null safety so that it might load properly idk --- Services/BatteryManager.qml | 8 +++++--- Services/BluetoothManager.qml | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index b5325eb..4f9f6ba 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -8,9 +8,11 @@ import "../Color.js" as Colors Singleton { id: root - property double batteryPercentage: root.mainBattery.percentage - property bool batteryPresent: root.mainBattery.ready - property UPowerDevice mainBattery: UPower.displayDevice + property double batteryPercentage: root.mainBattery.percentage || 0 + property bool batteryPresent: root.mainBattery.ready || false + property UPowerDevice mainBattery: UPower.displayDevice || undefined + + function getBatteryColor() { let criticalLevel = 20; diff --git a/Services/BluetoothManager.qml b/Services/BluetoothManager.qml index f3c268c..eaa1e5d 100644 --- a/Services/BluetoothManager.qml +++ b/Services/BluetoothManager.qml @@ -6,22 +6,29 @@ import Quickshell.Bluetooth Singleton { id: root - property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter - property string defaultAdapterName: Bluetooth.defaultAdapter.adapterId + property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter || null + property string defaultAdapterName: defaultAdapter ? defaultAdapter.adapterId : "" function getConnected() { let deviceList = getDevicesList(); - for (let device in deviceList) { - let currentDevice = deviceList[device]; - if (currentDevice.connected == true) { - return true; + if (deviceList.length == 0) { + return false; + } else { + for (let device in deviceList) { + let currentDevice = deviceList[device]; + if (currentDevice.connected == true) { + return true; + } } + return false; } - return false; } function getConnectedDevicesList() { let devicesList = getDevicesList(); + if (!devicesList) { + return []; + } let connectedList = []; for (let device of devicesList) { if (device.connected == true) { @@ -32,6 +39,9 @@ Singleton { } function getDeviceText(device) { + if (!device) { + return undefined; + } let deviceName = device.deviceName; let deviceIcon = getIcon(device.icon); let deviceMac = device.address; @@ -54,6 +64,9 @@ Singleton { } function getDevicesList() { + if (!root.defaultAdapter) { + return []; + } return root.defaultAdapter.devices.values; } From 79d83cbe37d5d9d4812da565bd9395f3ddc18cdb Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 12:23:50 +0100 Subject: [PATCH 29/38] had opencode fix my weird animation issues, now the bar loads correctly from a coldstart --- Bar/Battery.qml | 2 +- Bar/Bluetooth.qml | 2 +- Bar/Network.qml | 2 +- Components/Container.qml | 16 +++++++++++----- Services/BatteryManager.qml | 1 + Services/BluetoothManager.qml | 16 ++++------------ Services/NetworkManager.qml | 23 ++++++++++++++++++----- 7 files changed, 37 insertions(+), 25 deletions(-) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index 6e13996..e0de981 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -20,7 +20,7 @@ Container { boxRadius: radius defaultItem: icon exclusiveMonitor: root.monitor - forceHidden: !BatteryManager.mainBattery.isLaptopBattery + forceHidden: !BatteryManager.hasLaptopBattery states: [ State { diff --git a/Bar/Bluetooth.qml b/Bar/Bluetooth.qml index 7542f2d..0687db5 100644 --- a/Bar/Bluetooth.qml +++ b/Bar/Bluetooth.qml @@ -23,7 +23,7 @@ Container { defaultItem: icon exclusiveMonitor: root.monitor exclusiveToScreen: true - forceHidden: !(BluetoothManager.getConnected()) + forceHidden: !BluetoothManager.anyConnected states: [ State { diff --git a/Bar/Network.qml b/Bar/Network.qml index ddec3cf..3a40c6b 100644 --- a/Bar/Network.qml +++ b/Bar/Network.qml @@ -20,7 +20,7 @@ Container { defaultItem: icon exclusiveMonitor: root.monitor exclusiveToScreen: true - forceHidden: !NetworkManager.isConnectedAndWifi() + forceHidden: !NetworkManager.connectedWifi states: [ State { diff --git a/Components/Container.qml b/Components/Container.qml index 08302e5..5928f2c 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -42,7 +42,11 @@ Item { property double visibleTopMargin: 0 implicitHeight: boxHeight - implicitWidth: boxWidth + implicitWidth: root._widthCollapsed ? 0 : root.boxWidth + visible: !root._fullyHidden + + property bool _widthCollapsed: false + property bool _fullyHidden: false Behavior on anchors.topMargin { animation: defaultCurve @@ -70,8 +74,10 @@ Item { if (root.forceHidden == true) { hideTimer.restart(); } else { - root.implicitWidth = root.boxWidth; - root.visible = true; + hideTimer.stop(); + subHideTimer.stop(); + root._fullyHidden = false; + root._widthCollapsed = false; } } @@ -83,7 +89,7 @@ Item { running: false onTriggered: { - root.implicitWidth = 0; + root._widthCollapsed = true; subHideTimer.restart(); } } @@ -96,7 +102,7 @@ Item { running: false onTriggered: { - root.visible = false; + root._fullyHidden = true; } } diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index 4f9f6ba..c8cc381 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -11,6 +11,7 @@ Singleton { property double batteryPercentage: root.mainBattery.percentage || 0 property bool batteryPresent: root.mainBattery.ready || false property UPowerDevice mainBattery: UPower.displayDevice || undefined + property bool hasLaptopBattery: root.mainBattery && root.mainBattery.isLaptopBattery diff --git a/Services/BluetoothManager.qml b/Services/BluetoothManager.qml index eaa1e5d..92bdd20 100644 --- a/Services/BluetoothManager.qml +++ b/Services/BluetoothManager.qml @@ -9,19 +9,11 @@ Singleton { property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter || null property string defaultAdapterName: defaultAdapter ? defaultAdapter.adapterId : "" + property bool anyConnected: root.defaultAdapter != null + && root.defaultAdapter.devices.values.some(device => device.connected) + function getConnected() { - let deviceList = getDevicesList(); - if (deviceList.length == 0) { - return false; - } else { - for (let device in deviceList) { - let currentDevice = deviceList[device]; - if (currentDevice.connected == true) { - return true; - } - } - return false; - } + return root.anyConnected; } function getConnectedDevicesList() { diff --git a/Services/NetworkManager.qml b/Services/NetworkManager.qml index 8ac51b1..24d4fd1 100644 --- a/Services/NetworkManager.qml +++ b/Services/NetworkManager.qml @@ -8,6 +8,10 @@ Singleton { property NetworkDevice defaultAdapter: Networking.devices.values[0] + property bool connectedWifi: root.defaultAdapter != null + && root.defaultAdapter.connected + && root.defaultAdapter.type == DeviceType.Wifi + function getConnectedNetworks(networksArr) { let connectedNetworks = []; @@ -20,6 +24,17 @@ Singleton { } function getNetworkDetails(adapter) { + if (!adapter) { + return { + "adapterName": "", + "adapterConnected": false, + "adapterIsWifi": false, + "networkName": "", + "networkStrength": 0, + "icon": "󰤭" + }; + } + let networksArr = adapter.networks.values; let connectedNetworks = getConnectedNetworks(networksArr); let deviceWifi = isDeviceWifi(adapter); @@ -48,11 +63,9 @@ Singleton { return iconArr[strengthIndex - 1]; } - function isConnectedAndWifi() { - let isConnected = defaultAdapter.connected - let isWifi = isDeviceWifi(defaultAdapter) - return isConnected && isWifi - } + function isConnectedAndWifi() { + return root.connectedWifi; + } function getWifiText() { let info = getNetworkDetails(defaultAdapter); From 3250231384fcc237b80bae2bbde800119be3917a Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 12:48:27 +0100 Subject: [PATCH 30/38] animation offsets to look nice --- Bar/Battery.qml | 1 + Bar/Network.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index e0de981..d614d4c 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -16,6 +16,7 @@ Container { property bool opened: false property double radius: 9 + animOffset: 150 boxColor: Colors.green boxRadius: radius defaultItem: icon diff --git a/Bar/Network.qml b/Bar/Network.qml index 3a40c6b..dfce4f8 100644 --- a/Bar/Network.qml +++ b/Bar/Network.qml @@ -14,6 +14,7 @@ Container { required property HyprlandMonitor monitor property bool opened: false + animOffset: 250 boxColor: Colors.red boxHeight: 25 boxWidth: 33 From f2ed2e7a4e3ea912f37d1c001bc8fcd1eb68aa48 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 12:48:34 +0100 Subject: [PATCH 31/38] notifications working --- Bar/Time.qml | 93 +++++++++++++++++++++++++++++++- Services/NotificationManager.qml | 3 ++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/Bar/Time.qml b/Bar/Time.qml index 777a090..6108dca 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -1,7 +1,9 @@ +pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls import Quickshell import Quickshell.Hyprland +import Quickshell.Services.Notifications import "../Color.js" as Colors import "../Components/" @@ -10,32 +12,121 @@ import "../Services/" Container { id: root + property Notification latestNotif + property double latestNotifId: latestNotif.id || 0 required property HyprlandMonitor monitor + property bool notified: false + property bool overriden: false boxColor: Colors.mauve defaultItem: time exclusiveMonitor: root.monitor states: [ + State { + name: "closed" + when: root.hovered == false && root.overriden == false + + PropertyChanges { + root.boxHeight: 28 + root.boxRadius: 9 + root.boxWidth: 100 + } + + StateChangeScript { + script: { + if (root.stack.currentItem.component != "time") { + root.stack.replace(time); + } + } + } + }, State { name: "hovered" - when: root.hovered == true + when: root.hovered == true && root.overriden == false PropertyChanges { root.boxHeight: 32 root.boxRadius: 12 root.boxWidth: 107 } + + StateChangeScript { + script: { + root.stack.replace(time); + } + } + }, + State { + name: "notified" + when: root.notified == true + + PropertyChanges { + root.boxHeight: 32 + root.boxRadius: 12 + root.boxWidth: 200 + } + + StateChangeScript { + script: { + root.stack.replace(notification); + console.log("notification"); + notificationTimer.restart(); + } + } } ] + Connections { + function onNewNotification() { + notification => { + if (notification != root.latestNotif) { + root.latestNotif = notification; + root.overriden = true; + root.notified = true; + } else { + console.log("notif already called"); + } + }; + } + + target: NotificationManager + } + + Timer { + id: notificationTimer + + interval: 2000 + repeat: false + running: false + + onTriggered: { + root.notified = false; + root.overriden = false; + } + } + Component { id: time StyledText { + property string component: "time" + horizontalAlignment: Qt.AlignCenter text: Time.time verticalAlignment: Qt.AlignVCenter } } + + Component { + id: notification + + StyledText { + property string component: "notification" + + horizontalAlignment: Qt.AlignCenter + text: root.latestNotif.summary + verticalAlignment: Qt.AlignVCenter + } + } } diff --git a/Services/NotificationManager.qml b/Services/NotificationManager.qml index 02981e3..62677ea 100644 --- a/Services/NotificationManager.qml +++ b/Services/NotificationManager.qml @@ -8,6 +8,8 @@ Singleton { property alias notif: server + signal newNotification(notificiation: Notification) + function getLatestNotification() { let notificationList = server.trackedNotifications.values; let len = notificationList.length; @@ -27,6 +29,7 @@ Singleton { onNotification: notification => { notification.tracked = true; + root.newNotification(notification); } } } From 04e2ca54be86f9a117d57c5595f759be6e6f1e35 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 13:01:24 +0100 Subject: [PATCH 32/38] consistent wifi display (looks good) --- Bar/Network.qml | 76 ++++++++++++++++++++++++++++++++++--- Services/NetworkManager.qml | 17 ++++----- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/Bar/Network.qml b/Bar/Network.qml index dfce4f8..8435dc1 100644 --- a/Bar/Network.qml +++ b/Bar/Network.qml @@ -12,6 +12,7 @@ Container { id: root required property HyprlandMonitor monitor + property double networkDisplayHeight: 80 property bool opened: false animOffset: 250 @@ -48,7 +49,7 @@ Container { when: root.opened == true && root.hovered == true PropertyChanges { - root.boxHeight: 28 + root.boxHeight: root.networkDisplayHeight root.boxRadius: 12 root.boxWidth: 350 } @@ -87,11 +88,74 @@ Container { Component { id: wifiInfo - StyledText { - horizontalAlignment: Qt.AlignCenter - propo: true - text: NetworkManager.getWifiText() - verticalAlignment: Qt.AlignVCenter + Item { + id: networkDisplayRoot + + property double innerMargin: 5 + property double outerMargin: 6 + + Rectangle { + id: networkDisplayBg + + anchors.fill: parent + anchors.margins: networkDisplayRoot.outerMargin + color: Colors.surface1 + radius: 8 + + RowLayout { + anchors.fill: parent + + Rectangle { + id: iconBox + + property double iconBoxRadius: 5 + + Layout.fillHeight: true + Layout.margins: networkDisplayRoot.innerMargin + color: Colors.red + implicitWidth: root.networkDisplayHeight - (networkDisplayRoot.innerMargin * 2) - ( + networkDisplayRoot.outerMargin * 2) + radius: 5 + + CenteredText { + fontSize: 23 + propo: true + text: NetworkManager.getNetworkDetails(NetworkManager.defaultAdapter)["icon"] + } + } + + Column { + id: networkColumn + + property var networkInfo: NetworkManager.getNetworkDetails(NetworkManager.defaultAdapter) + + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + + StyledText { + color: Colors.text + fontSize: 14 + text: networkColumn.networkInfo["networkName"] + } + + StyledText { + color: Colors.subtext1 + fontSize: 12 + fontWeight: 5 + text: "Connected on: " + networkColumn.networkInfo["adapterName"] + } + + StyledText { + property var timeInfo: networkColumn.networkInfo["time"] + + color: Colors.subtext1 + fontSize: 12 + fontWeight: 5 + text: "Network Details " + (networkColumn.networkInfo["saved"] == true ? "Saved" : "Not Saved") + } + } + } + } } } } diff --git a/Services/NetworkManager.qml b/Services/NetworkManager.qml index 24d4fd1..13e3698 100644 --- a/Services/NetworkManager.qml +++ b/Services/NetworkManager.qml @@ -6,12 +6,10 @@ import Quickshell.Networking Singleton { id: root + property bool connectedWifi: root.defaultAdapter != null && root.defaultAdapter.connected + && root.defaultAdapter.type == DeviceType.Wifi property NetworkDevice defaultAdapter: Networking.devices.values[0] - property bool connectedWifi: root.defaultAdapter != null - && root.defaultAdapter.connected - && root.defaultAdapter.type == DeviceType.Wifi - function getConnectedNetworks(networksArr) { let connectedNetworks = []; @@ -52,7 +50,8 @@ Singleton { "adapterIsWifi": deviceWifi, "networkName": networkName, "networkStrength": networkStrength, - "icon": networkIcon + "icon": networkIcon, + "saved": primaryNetwork.known }; return outputDict; } @@ -63,10 +62,6 @@ Singleton { return iconArr[strengthIndex - 1]; } - function isConnectedAndWifi() { - return root.connectedWifi; - } - function getWifiText() { let info = getNetworkDetails(defaultAdapter); @@ -77,6 +72,10 @@ Singleton { return finalString; } + function isConnectedAndWifi() { + return root.connectedWifi; + } + function isDeviceWifi(adapter) { if (adapter.type == DeviceType.Wifi) { return true; From 9f72a8abadbca97b352ef8621a3d44b257793993 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 15:37:30 +0100 Subject: [PATCH 33/38] formatting --- Components/Container.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Components/Container.qml b/Components/Container.qml index 5928f2c..611cd8e 100644 --- a/Components/Container.qml +++ b/Components/Container.qml @@ -9,6 +9,8 @@ import "../Color.js" as Colors Item { id: root + property bool _fullyHidden: false + property bool _widthCollapsed: false property double animOffset: 0 property color boxColor: Colors.surface0 property double boxHeight: 28 @@ -45,9 +47,6 @@ Item { implicitWidth: root._widthCollapsed ? 0 : root.boxWidth visible: !root._fullyHidden - property bool _widthCollapsed: false - property bool _fullyHidden: false - Behavior on anchors.topMargin { animation: defaultCurve } From 1c5a25c8faaadb56cb99f673535b03aeebc3c9de Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 15:37:46 +0100 Subject: [PATCH 34/38] null safety to remove warnings --- Bar/Network.qml | 2 +- Services/NetworkManager.qml | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Bar/Network.qml b/Bar/Network.qml index 8435dc1..8bfc485 100644 --- a/Bar/Network.qml +++ b/Bar/Network.qml @@ -80,7 +80,7 @@ Container { StyledText { horizontalAlignment: Qt.AlignCenter propo: true - text: NetworkManager.getNetworkDetails(NetworkManager.defaultAdapter)["icon"] + text: NetworkManager.getNetworkDetails(NetworkManager.defaultAdapter)["icon"] || "󰤭" verticalAlignment: Qt.AlignVCenter } } diff --git a/Services/NetworkManager.qml b/Services/NetworkManager.qml index 13e3698..f7ee42c 100644 --- a/Services/NetworkManager.qml +++ b/Services/NetworkManager.qml @@ -8,7 +8,7 @@ Singleton { property bool connectedWifi: root.defaultAdapter != null && root.defaultAdapter.connected && root.defaultAdapter.type == DeviceType.Wifi - property NetworkDevice defaultAdapter: Networking.devices.values[0] + property NetworkDevice defaultAdapter: Networking.devices.values[0] || null function getConnectedNetworks(networksArr) { let connectedNetworks = []; @@ -38,6 +38,16 @@ Singleton { let deviceWifi = isDeviceWifi(adapter); let primaryNetwork = connectedNetworks[0]; + if (!primaryNetwork) { + return { + "adapterName": adapter.name, + "adapterConnected": adapter.connected, + "adapterIsWifi": deviceWifi, + "networkName": "No Network", + "networkStrength": 0, + "icon": "󰤭" + }; + } let networkName = primaryNetwork.name; let networkStrength = primaryNetwork.signalStrength; From 0203236575b92abce5df1bb6aac6d30ec66d9d43 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 15:38:02 +0100 Subject: [PATCH 35/38] notifications working perfectly they look so cool --- Bar/Time.qml | 87 +++++++++++++++++++++++++++----- Services/NotificationManager.qml | 2 + 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/Bar/Time.qml b/Bar/Time.qml index 6108dca..9e33d52 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -1,9 +1,11 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Hyprland import Quickshell.Services.Notifications +import Quickshell.Widgets import "../Color.js" as Colors import "../Components/" @@ -13,8 +15,9 @@ Container { id: root property Notification latestNotif - property double latestNotifId: latestNotif.id || 0 required property HyprlandMonitor monitor + property double notificationHeight: 100 + property double notificationWidth: 350 property bool notified: false property bool overriden: false @@ -35,6 +38,9 @@ Container { StateChangeScript { script: { + if (!root.stack.currentItem) { + return; + } if (root.stack.currentItem.component != "time") { root.stack.replace(time); } @@ -62,15 +68,15 @@ Container { when: root.notified == true PropertyChanges { - root.boxHeight: 32 + root.boxHeight: root.notificationHeight root.boxRadius: 12 - root.boxWidth: 200 + root.boxWidth: root.notificationWidth + root.visibleTopMargin: 5 } StateChangeScript { script: { root.stack.replace(notification); - console.log("notification"); notificationTimer.restart(); } } @@ -80,12 +86,10 @@ Container { Connections { function onNewNotification() { notification => { - if (notification != root.latestNotif) { + if (notification.lastGeneration == false) { root.latestNotif = notification; root.overriden = true; root.notified = true; - } else { - console.log("notif already called"); } }; } @@ -121,12 +125,71 @@ Container { Component { id: notification - StyledText { - property string component: "notification" + Item { + id: notificationRoot - horizontalAlignment: Qt.AlignCenter - text: root.latestNotif.summary - verticalAlignment: Qt.AlignVCenter + property double innerMargin: 5 + property double outerMargin: 6 + + function getInnerHeight() { + let fullHeight = root.notificationHeight; + let fullMargin = notificationRoot.innerMargin + notificationRoot.outerMargin; + + return fullHeight - (fullMargin * 2); + } + + Rectangle { + color: Colors.surface1 + radius: 9 + + anchors { + fill: parent + margins: notificationRoot.outerMargin + } + + RowLayout { + Rectangle { + Layout.margins: notificationRoot.innerMargin + color: Colors.mauve + implicitHeight: notificationRoot.getInnerHeight() + implicitWidth: notificationRoot.getInnerHeight() + radius: 5 + + IconImage { + anchors.fill: parent + anchors.margins: 10 + source: root.latestNotif.image + } + } + + ColumnLayout { + property double textMargin: 4 + + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.leftMargin: 0 + Layout.margins: notificationRoot.innerMargin + textMargin + + StyledText { + color: Colors.text + fontSize: 14 + text: root.latestNotif.summary + } + + StyledText { + Layout.fillHeight: true + Layout.maximumWidth: root.notificationWidth - ((notificationRoot.outerMargin * 2) + ( + notificationRoot.innerMargin * 3) + notificationRoot.getInnerHeight()) + color: Colors.subtext0 + elide: Qt.ElideRight + fontWeight: 5 + maximumLineCount: 2 + text: root.latestNotif.body + wrapMode: Text.WordWrap + } + } + } + } } } } diff --git a/Services/NotificationManager.qml b/Services/NotificationManager.qml index 62677ea..edbb714 100644 --- a/Services/NotificationManager.qml +++ b/Services/NotificationManager.qml @@ -2,6 +2,7 @@ pragma Singleton import QtQuick import Quickshell import Quickshell.Services.Notifications +import "../Color.js" as Colors Singleton { id: root @@ -26,6 +27,7 @@ Singleton { actionsSupported: true bodyMarkupSupported: true bodySupported: true + imageSupported: true onNotification: notification => { notification.tracked = true; From 6cce5006709cb2271494f7c012c56e326924e8e5 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 17:02:40 +0100 Subject: [PATCH 36/38] mpris popup working --- Bar/Time.qml | 141 ++++++++++++++++++++++++++++++++++++++ Services/MprisManager.qml | 52 +++++++++++++- 2 files changed, 191 insertions(+), 2 deletions(-) diff --git a/Bar/Time.qml b/Bar/Time.qml index 9e33d52..56c569d 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -16,6 +16,9 @@ Container { property Notification latestNotif required property HyprlandMonitor monitor + property bool mpris: false + property double mprisHeight: 60 + property double mprisWidth: 350 property double notificationHeight: 100 property double notificationWidth: 350 property bool notified: false @@ -80,6 +83,24 @@ Container { notificationTimer.restart(); } } + }, + State { + name: "mpris" + when: root.mpris == true + + PropertyChanges { + root.boxHeight: root.mprisHeight + root.boxRadius: 12 + root.boxWidth: root.mprisWidth + root.visibleTopMargin: 5 + } + + StateChangeScript { + script: { + root.stack.replace(mprisToast); + mprisTimer.restart(); + } + } } ] @@ -97,6 +118,16 @@ Container { target: NotificationManager } + Connections { + function onTrackChanged() { + root.overriden = true; + root.mpris = true; + console.log("track changed"); + } + + target: MprisManager.defaultPlayer + } + Timer { id: notificationTimer @@ -110,6 +141,19 @@ Container { } } + Timer { + id: mprisTimer + + interval: 2000 + repeat: false + running: false + + onTriggered: { + root.mpris = false; + root.overriden = false; + } + } + Component { id: time @@ -192,4 +236,101 @@ Container { } } } + + Component { + id: mprisToast + + Item { + id: mprisToastRoot + + property double innerMargin: 4 + property double outerMargin: 4 + property var trackInfo: MprisManager.getTrackInfo() + + function getInnerHeight() { + let fullHeight = root.mprisHeight; + let fullMargin = mprisToastRoot.innerMargin + mprisToastRoot.outerMargin; + + return fullHeight - (fullMargin * 2); + } + + Rectangle { + color: Colors.surface1 + radius: 9 + + anchors { + fill: parent + margins: mprisToastRoot.outerMargin + } + + RowLayout { + Rectangle { + Layout.margins: mprisToastRoot.innerMargin + color: Colors.mauve + implicitHeight: mprisToastRoot.getInnerHeight() + implicitWidth: mprisToastRoot.getInnerHeight() + radius: 5 + + IconImage { + anchors.fill: parent + source: mprisToastRoot.trackInfo["albumArt"] + } + } + + ColumnLayout { + property double textMargin: 1 + + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.leftMargin: 0 + Layout.margins: mprisToastRoot.innerMargin + textMargin + + StyledText { + Layout.maximumWidth: root.mprisWidth - ((mprisToastRoot.outerMargin * 2) + ( + mprisToastRoot.innerMargin * 5) + mprisToastRoot.getInnerHeight()) + color: Colors.text + fontSize: 14 + text: mprisToastRoot.trackInfo["name"] + " - " + mprisToastRoot.trackInfo["artist"] + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.maximumWidth: root.mprisWidth - ((mprisToastRoot.outerMargin * 2) + ( + mprisToastRoot.innerMargin * 5) + mprisToastRoot.getInnerHeight()) + Layout.preferredWidth: root.mprisWidth - ((mprisToastRoot.outerMargin * 2) + ( + mprisToastRoot.innerMargin * 5) + mprisToastRoot.getInnerHeight()) + + Rectangle { + anchors.fill: parent + color: Colors.overlay0 + radius: 100 + + Rectangle { + color: Colors.mauve + implicitWidth: parent.width * mprisToastRoot.trackInfo["lengthPercent"] + radius: 100 + + anchors { + bottom: parent.bottom + left: parent.left + top: parent.top + } + } + + StyledText { + text: MprisManager.getTimeString() + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + } + } + } + } + } + } + } + } } diff --git a/Services/MprisManager.qml b/Services/MprisManager.qml index 95cf458..089bb50 100644 --- a/Services/MprisManager.qml +++ b/Services/MprisManager.qml @@ -6,8 +6,7 @@ import Quickshell.Services.Mpris Singleton { id: root - property MprisPlayer defaultPlayer: Mpris.players.values[0] - property real pos: defaultPlayer.position / defaultPlayer.length + property MprisPlayer defaultPlayer: Mpris.players.values[0] || null function getPlaying() { if (!defaultPlayer) { @@ -17,6 +16,55 @@ Singleton { } } + function getTimeString() { + let trackInfo = getTrackInfo(); + let position = trackInfo["position"]; + let length = trackInfo["length"]; + if (length.hours > 0) { + return position.hours + ":" + position.minutes + ":" + position.seconds + "/" + length.hours + + ":" + length.minutes + ":" + length.seconds; + } else { + return position.minutes + ":" + position.seconds + "/" + length.minutes + ":" + length.seconds; + } + } + + function getTrackInfo() { + let trackName = root.defaultPlayer.trackTitle; + let trackArtist = root.defaultPlayer.trackArtist; + let trackAlbum = root.defaultPlayer.trackAlbum; + let trackPosition = root.defaultPlayer.position; + let trackLength = root.defaultPlayer.length; + let trackArt = root.defaultPlayer.trackArtUrl; + return { + "name": trackName, + "artist": trackArtist, + "album": trackAlbum, + "position": msToArray(trackPosition), + "length": msToArray(trackLength), + "lengthRemaining": msToArray(trackLength - trackPosition), + "lengthPercent": trackPosition / trackLength, + "albumArt": trackArt + }; + } + + function msToArray(time) { + time = Math.max(0, Number(time)); + + const inthours = Math.floor(time / 3600000); + const intminutes = Math.floor((time % 60000) / 60); + const intseconds = Math.floor((time % 1000) % 60); + + const hours = String(inthours).padStart(2, "0"); + const minutes = String(intminutes).padStart(2, "0"); + const seconds = String(intseconds).padStart(2, "0"); + + return { + hours, + minutes, + seconds + }; + } + function prev() { defaultPlayer.previous(); } From 006697b768321664650d98b9005c0cbf98821f15 Mon Sep 17 00:00:00 2001 From: voidarc Date: Sun, 9 Aug 2026 17:06:09 +0100 Subject: [PATCH 37/38] hover for mpris working --- Bar/Time.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bar/Time.qml b/Bar/Time.qml index 56c569d..54fb987 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -55,14 +55,14 @@ Container { when: root.hovered == true && root.overriden == false PropertyChanges { - root.boxHeight: 32 + root.boxHeight: MprisManager.getPlaying() == false ? 32 : root.mprisHeight root.boxRadius: 12 - root.boxWidth: 107 + root.boxWidth: MprisManager.getPlaying() == false ? 107 : root.mprisWidth } StateChangeScript { script: { - root.stack.replace(time); + root.stack.replace(MprisManager.getPlaying() == true ? mprisToast : time); } } }, @@ -144,7 +144,7 @@ Container { Timer { id: mprisTimer - interval: 2000 + interval: 3000 repeat: false running: false From d7de61fac8e6ba5a4f4b66a5d9235e632b3bd9ce Mon Sep 17 00:00:00 2001 From: voidarc Date: Mon, 10 Aug 2026 13:25:57 +0100 Subject: [PATCH 38/38] formatting and adding exclusivetoscreen to the right modules --- Bar/Battery.qml | 3 ++- Bar/Time.qml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Bar/Battery.qml b/Bar/Battery.qml index d614d4c..99b4a6e 100644 --- a/Bar/Battery.qml +++ b/Bar/Battery.qml @@ -16,11 +16,12 @@ Container { property bool opened: false property double radius: 9 - animOffset: 150 + animOffset: 150 boxColor: Colors.green boxRadius: radius defaultItem: icon exclusiveMonitor: root.monitor + exclusiveToScreen: true forceHidden: !BatteryManager.hasLaptopBattery states: [ diff --git a/Bar/Time.qml b/Bar/Time.qml index 54fb987..1768ea9 100644 --- a/Bar/Time.qml +++ b/Bar/Time.qml @@ -27,6 +27,7 @@ Container { boxColor: Colors.mauve defaultItem: time exclusiveMonitor: root.monitor + exclusiveToScreen: true states: [ State {