diff --git a/Colors.qml b/Colors.qml index 0e0a638..1ffcaa8 100644 --- a/Colors.qml +++ b/Colors.qml @@ -5,7 +5,7 @@ import Quickshell Singleton { id: customColors // Core Backgrounds - readonly property color background: "#1A1B26" + readonly property color background: "#24283B" readonly property color foreground: "#C0CAF5" readonly property color cursor: "#C0CAF5" @@ -17,7 +17,7 @@ Singleton { readonly property color color4: "#7AA2F7" readonly property color color5: "#BB9AF7" readonly property color color6: "#7DCFFF" - readonly property color color7: "#A9B1D6" + readonly property color color7: "#C0CAF5" readonly property color color8: "#414868" readonly property color color9: "#F7768E" readonly property color color10: "#9ECE6A" diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index b03d083..f5b9181 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -8,7 +8,7 @@ PanelWindow { required property var modelData implicitHeight: 30 //color: Colors.background - color: "black" + color: Colors.background anchors { top: true left: true @@ -17,11 +17,13 @@ PanelWindow { RowLayout { id: leftLayout + spacing: 30 anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter Clock { Layout.leftMargin: 30 } + Mpris {} } RowLayout { @@ -37,6 +39,7 @@ PanelWindow { anchors.verticalCenter: parent.verticalCenter Volume {} Battery {} + PowerProfiles {} SystemTray { Layout.rightMargin: 30 } diff --git a/modules/bar/Battery.qml b/modules/bar/Battery.qml index 6a8d938..23e7fbe 100644 --- a/modules/bar/Battery.qml +++ b/modules/bar/Battery.qml @@ -27,26 +27,5 @@ Item { color: Colors.foreground text: Math.round(UPower.displayDevice.percentage * 100) + "%" } - Text { - id: powerProfile - text: PowerProfile.toString(PowerProfiles.profile) - font.weight: 900 - color: Colors.foreground - font.family: Appearance.font - font.pixelSize: Appearance.fontSize - } - } - MouseArea { - acceptedButtons: Qt.LeftButton - cursorShape: Qt.OpenHandCursor - anchors.fill: parent - onClicked: { - const modes = [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]; - let current = PowerProfiles.profile; - let currentIndex = modes.indexOf(current); - let nextIndex = (currentIndex + 1) % modes.length; - PowerProfiles.profile = modes[nextIndex]; - PowerProfiles.profile = profiles[nextIndex]; - } } } diff --git a/modules/bar/Mpris.qml b/modules/bar/Mpris.qml new file mode 100644 index 0000000..8e3358e --- /dev/null +++ b/modules/bar/Mpris.qml @@ -0,0 +1,134 @@ +// ⚠️ Ensure Colors is imported +// import "../../" +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.Mpris +import qs + +RowLayout { + id: root + + // 1. Let Repeater loop through the ObjectModel for us + Repeater { + id: mprisRepeater + model: Mpris.players + + delegate: RowLayout { + required property var modelData + // 2. 🕵️‍♀️ FILTER LOGIC + // Check if this specific player is Spotify. + // We verify 'modelData' exists and check the name. + property bool isSpotify: modelData && modelData.identity.toLowerCase().includes("spotify") + + // 3. 👻 HIDE NON-SPOTIFY PLAYERS + visible: isSpotify + + // If hidden, take up ZERO space + Layout.preferredWidth: isSpotify ? Math.min(implicitWidth, 400) : 0 + Layout.fillHeight: true + + // 4. 🎵 USE 'modelData' DIRECTLY + // property string title: modelData.metadata["xesam:title"] || "No Title" + // property string artist: modelData.metadata["xesam:artist"] || "Unknown" + // property string artUrl: modelData.metadata["mpris:artUrl"] || "" + // property bool isPlaying: modelData.playbackStatus === MprisPlaybackStatus.Playing + property string title: modelData.trackTitle + property string artist: modelData.trackArtist + property string artUrl: modelData.trackArtUrl + property bool isPlaying: modelData.isPlaying + + spacing: 8 + + // 🖼️ ALBUM ART + Rectangle { + Layout.preferredHeight: parent.height * 0.8 + Layout.preferredWidth: Layout.preferredHeight + Layout.alignment: Qt.AlignVCenter + + radius: 4 + color: Colors.background + clip: true + visible: parent.visible // Optimization + + Image { + anchors.fill: parent + source: parent.parent.artUrl // Access property from delegate + fillMode: Image.PreserveAspectCrop + asynchronous: true + sourceSize.width: 128 + sourceSize.height: 128 + } + } + + // 📝 TEXT INFO + ColumnLayout { + Layout.alignment: Qt.AlignVCenter + spacing: 0 + visible: parent.visible + + Text { + text: parent.parent.title + color: Colors.foreground + font.bold: true + font.pixelSize: 12 + elide: Text.ElideRight + Layout.preferredWidth: implicitWidth + } + + Text { + text: parent.parent.artist + color: Colors.foreground + opacity: 0.7 + font.pixelSize: 10 + Layout.preferredWidth: implicitWidth + } + } + + // ⏯️ CONTROLS + RowLayout { + Layout.alignment: Qt.AlignVCenter + spacing: 8 + visible: parent.visible + + // PREV + Text { + text: "󰒮" + color: Colors.foreground + font.pixelSize: 24 + MouseArea { + anchors.fill: parent + // Use modelData to control THIS player + onClicked: modelData.previous() + cursorShape: Qt.PointingHandCursor + } + } + + // PLAY / PAUSE + Text { + text: parent.parent.isPlaying ? "󰏤" : "󰐊" + color: Colors.foreground + font.pixelSize: 24 + MouseArea { + anchors.fill: parent + onClicked: modelData.playPause() + cursorShape: Qt.PointingHandCursor + } + } + + // NEXT + Text { + text: "󰒭" + color: Colors.foreground + font.pixelSize: 24 + MouseArea { + anchors.fill: parent + onClicked: modelData.next() + cursorShape: Qt.PointingHandCursor + } + } + } + } + } +} diff --git a/modules/bar/PowerProfiles.qml b/modules/bar/PowerProfiles.qml new file mode 100644 index 0000000..3d03f58 --- /dev/null +++ b/modules/bar/PowerProfiles.qml @@ -0,0 +1,33 @@ +import QtQuick +import Quickshell.Services.UPower +import qs + +Item { + id: root + implicitWidth: 80 + Text { + id: powerProfile + text: PowerProfile.toString(PowerProfiles.profile) + font.weight: 900 + color: Colors.foreground + font.family: Appearance.font + font.pixelSize: Appearance.fontSize + anchors.centerIn: parent + MouseArea { + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.OpenHandCursor + anchors.fill: parent + onClicked: mouse => { + const modes = [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]; + let current = PowerProfiles.profile; + let currentIndex = modes.indexOf(current); + let nextIndex = (currentIndex + 1) % modes.length; + let prevIndex = (currentIndex - 1) % modes.length; + if (mouse.button == Qt.LeftButton) + PowerProfiles.profile = modes[nextIndex]; + if (mouse.button == Qt.RightButton) + PowerProfiles.profile = modes[prevIndex]; + } + } + } +} diff --git a/modules/bar/Volume.qml b/modules/bar/Volume.qml index 4b71d90..95d0468 100644 --- a/modules/bar/Volume.qml +++ b/modules/bar/Volume.qml @@ -73,6 +73,8 @@ Item { objects: Pipewire.defaultAudioSink } + anchors.verticalCenter: parent.verticalCenter + width: 20 font.weight: 900 color: Colors.foreground font.family: Appearance.font diff --git a/modules/notifications/NotiPopup.qml b/modules/notifications/NotiPopup.qml index b87eac9..b2cd70c 100644 --- a/modules/notifications/NotiPopup.qml +++ b/modules/notifications/NotiPopup.qml @@ -59,7 +59,7 @@ WlrLayershell { required property var modelData Timer { id: timout - interval: 5000 + interval: 30000 running: true onRunningChanged: notifyItem.modelData.dismiss() } @@ -67,27 +67,30 @@ WlrLayershell { Rectangle { anchors.fill: parent color: Colors.background - radius: 20 + radius: 10 border.color: Colors.color5 // 2. Use RowLayout to put Image | Text side-by-side - RowLayout { - anchors.fill: parent + Row { anchors.margins: 10 + anchors.fill: parent + anchors.centerIn: parent spacing: 15 // 🖼️ THE IMAGE ON THE LEFT Image { + // Use the image if available, otherwise hide this space? // Or you could use an icon fallback. source: notifyItem.modelData.image + anchors.verticalCenter: parent.verticalCenter // Hide if no image exists so text takes full width visible: notifyItem.modelData.image !== "" // Fixed size for consistency - Layout.preferredWidth: 48 - Layout.preferredHeight: 48 + width: 48 + height: 48 // Crop it nicely so it doesn't stretch fillMode: Image.PreserveAspectCrop @@ -100,7 +103,7 @@ WlrLayershell { ColumnLayout { // Take up all remaining width Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter // Center vertically + Layout.alignment: Qt.AlignVCenter | Qt.AlignTop // Center vertically spacing: 2 Text { @@ -128,6 +131,8 @@ WlrLayershell { // (Your MouseArea for closing can still go here covering the whole thing) MouseArea { anchors.fill: parent + Layout.fillWidth: true + Layout.fillHeight: true acceptedButtons: Qt.LeftButton onClicked: notifyItem.modelData.dismiss() } diff --git a/modules/wallpaper/Overlay.qml b/modules/wallpaper/Overlay.qml index 92b93a2..85ab3cb 100644 --- a/modules/wallpaper/Overlay.qml +++ b/modules/wallpaper/Overlay.qml @@ -1,7 +1,8 @@ import QtQuick import Quickshell import Quickshell.Wayland -import "." // <--- Ensures we can find ScreenCorners.qml +import "../../" +import "." WlrLayershell { id: overlayRoot @@ -29,7 +30,7 @@ WlrLayershell { ScreenCorners { // Adjust these to match your screen's aesthetic cornerRadius: 25 - cornerColor: "black" + cornerColor: Colors.background shouldShow: true // Ensure it stays on top of any other items in this window diff --git a/modules/wallpaper/ScreenCorners.qml b/modules/wallpaper/ScreenCorners.qml index 5f1c67c..0494c9b 100644 --- a/modules/wallpaper/ScreenCorners.qml +++ b/modules/wallpaper/ScreenCorners.qml @@ -1,8 +1,5 @@ import QtQuick import QtQuick.Shapes -import qs - -// removed "import qs.Commons" because you don't have it! Item { id: root @@ -17,7 +14,7 @@ Item { // What color should the corners be? (Usually black to match the bezel) // You can change this to "transparent" or a theme color if you want. - property color cornerColor: Colors.background + property color cornerColor // Enable/Disable toggle property bool shouldShow: true @@ -52,8 +49,7 @@ Item { readonly property real screenHeight: cornersShape.height strokeWidth: -1 // No outline - //fillColor: Colors.background - fillColor: "black" + fillColor: cornerColor // Smooth fade if you toggle it diff --git a/modules/wallpaper/Wallpaper.qml b/modules/wallpaper/Wallpaper.qml index ea8e2fd..67ddf68 100644 --- a/modules/wallpaper/Wallpaper.qml +++ b/modules/wallpaper/Wallpaper.qml @@ -21,9 +21,8 @@ WlrLayershell { // 1. The StackView manages the images StackView { id: wallStack - anchors.fill: parent - implicitWidth: Screen.width - implicitHeight: Screen.height + width: parent.width + height: parent.height // 2. Define what a "Wallpaper" looks like Component {