From 6db876fc8a55210783d25e14f4a713c77f245638 Mon Sep 17 00:00:00 2001 From: SomeElse Date: Sun, 17 May 2026 22:30:27 +0000 Subject: [PATCH] small component patches + code cleanup --- bar/Bar.qml | 5 +- bar/modules/Battery.qml | 72 +++----- bar/modules/Clock.qml | 65 +++---- bar/modules/Crypto.qml | 302 ++++++++++++++------------------ bar/modules/Logo.qml | 18 +- bar/modules/Network.qml | 39 ++--- bar/modules/Notifications.qml | 24 +-- bar/modules/Stats.qml | 12 +- bar/modules/Tray.qml | 72 +++----- bar/modules/Volume.qml | 82 +++------ bar/modules/Workspace.qml | 6 +- components/ConfigWriter.qml | 68 +++++++ components/HoverButton.qml | 34 ++++ components/ModuleChip.qml | 40 +++++ components/PopupCard.qml | 13 ++ components/StandardPopup.qml | 31 ++++ components/TimezoneProvider.qml | 2 +- config/config.qml | 8 +- polkit/Polkit.qml | 38 ++-- shell.qml | 2 +- widgets/bgDate/BgDate.qml | 1 + 21 files changed, 469 insertions(+), 465 deletions(-) create mode 100644 components/ConfigWriter.qml create mode 100644 components/HoverButton.qml create mode 100644 components/StandardPopup.qml diff --git a/bar/Bar.qml b/bar/Bar.qml index 87807df..a7362eb 100644 --- a/bar/Bar.qml +++ b/bar/Bar.qml @@ -73,7 +73,6 @@ PanelWindow { item.height = Qt.binding(() => barContent.height - 12) const props = { - "panelRadius": cfg.radius / 2, "borderWidth": cfg.panelBorderWidth, "isTop": barWindow.isTop, "targetScreen": barWindow.modelData, @@ -95,7 +94,7 @@ PanelWindow { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter height: parent.height - width: Math.max(0, Math.min(leftRow.implicitWidth, barContent.sideMaxWidth)) + width: Math.min(leftRow.implicitWidth, barContent.sideMaxWidth) clip: true Row { @@ -123,7 +122,7 @@ PanelWindow { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter height: parent.height - width: Math.max(0, Math.min(rightRow.implicitWidth, barContent.sideMaxWidth)) + width: Math.min(rightRow.implicitWidth, barContent.sideMaxWidth) clip: true Row { diff --git a/bar/modules/Battery.qml b/bar/modules/Battery.qml index 26deca7..4971521 100644 --- a/bar/modules/Battery.qml +++ b/bar/modules/Battery.qml @@ -51,11 +51,11 @@ ModuleChip { readonly property bool isLow: batReady && !charging && pct <= 30 readonly property color iconColor: { - if (fullCharge) return t.batteryFull ?? t.accent - if (charging) return t.batteryCharging ?? t.accent - if (isCritical) return t.batteryCritical ?? "#ff5555" - if (isLow) return t.batteryLow ?? "#ffb86c" - return t.batteryIcon ?? t.clockIcon + if (fullCharge) return t.batteryFull + if (charging) return t.batteryCharging + if (isCritical) return t.batteryCritical + if (isLow) return t.batteryLow + return t.batteryIcon } readonly property var up: UPower @@ -92,21 +92,17 @@ ModuleChip { return names } + chipColor: t.batBg + chipColorHovered: t.batBgHover + chipBorderColor: t.batBorder + chipBorderColorHovered: t.batBorderHover + chipHoverEnabled: true + chipTapAction: () => batteryPopup.toggle() + chipAnimWidth: true + width: batLayout.implicitWidth + 24 - height: Cfg.Config.moduleHeight radius: panelRadius - color: hoverHandler.hovered ? t.batBgHover : t.batBg - border.color: hoverHandler.hovered ? t.batBorderHover : t.batBorder - border.width: borderWidth - - Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - - HoverHandler { id: hoverHandler; cursorShape: Qt.PointingHandCursor } - TapHandler { onTapped: batteryPopup.toggle() } - RowLayout { id: batLayout anchors.centerIn: parent @@ -144,8 +140,8 @@ ModuleChip { font.bold: true verticalAlignment: Text.AlignVCenter - opacity: (hoverHandler.hovered || batteryPopup.popupOpen) ? 1.0 : 0.0 - Layout.preferredWidth: (hoverHandler.hovered || batteryPopup.popupOpen) + opacity: (root.hovered || batteryPopup.popupOpen) ? 1.0 : 0.0 + Layout.preferredWidth: (root.hovered || batteryPopup.popupOpen) ? implicitWidth : 0 clip: true @@ -154,40 +150,19 @@ ModuleChip { } } - PopupPanel { + StandardPopup { id: batteryPopup ns: "battery" chipRoot: root cardWidth: 260 + cardColor: t.batPopupBg + cardBorderColor: t.batPopupBorder + cardHeight: cardCol.implicitHeight + 28 + showShadow: true + layerEnabled: true - Rectangle { - id: cardShadow - anchors.fill: card - anchors.margins: -3 - radius: card.radius + 3 - color: "transparent" - border.color: Qt.rgba(0, 0, 0, 0.35) - border.width: 6 - visible: batteryPopup.popupOpen - opacity: batteryPopup.popupOpen ? 0.6 : 0 - Behavior on opacity { NumberAnimation { duration: 200 } } - } - - PopupCard { - id: card - popupOpen: batteryPopup.popupOpen - isTop: root.isTop - animEnabled: batteryPopup.visible - height: cardCol.implicitHeight + 28 - - color: root.t.batPopupBg - radius: Cfg.Config.popupRadius - border.color: root.t.batPopupBorder - border.width: Cfg.Config.popupBorderWidth - layer.enabled: true - - ColumnLayout { - id: cardCol + ColumnLayout { + id: cardCol anchors { left: parent.left right: parent.right @@ -514,6 +489,5 @@ ModuleChip { Item { height: 2 } } - } } } diff --git a/bar/modules/Clock.qml b/bar/modules/Clock.qml index c658ac0..fc5392b 100644 --- a/bar/modules/Clock.qml +++ b/bar/modules/Clock.qml @@ -9,29 +9,17 @@ import "../../components" ModuleChip { id: root + chipColor: t.clockBg + chipColorHovered: t.clockBgHover + chipBorderColor: t.clockBorder + chipBorderColorHovered: t.clockBorderHover + chipHoverEnabled: true + chipTapAction: () => calendarPopup.toggle() + chipAnimWidth: true + width: clockLayout.implicitWidth + 24 - height: Cfg.Config.moduleHeight radius: panelRadius - color: hoverHandler.hovered ? t.clockBgHover : t.clockBg - border.color: hoverHandler.hovered ? t.clockBorderHover : t.clockBorder - border.width: borderWidth - - anchors.right: parent.right - - Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - - HoverHandler { - id: hoverHandler - cursorShape: Qt.PointingHandCursor - } - - TapHandler { - onTapped: calendarPopup.toggle() - } - Item { id: timeManager property date now: new Date() @@ -70,9 +58,9 @@ ModuleChip { font.bold: true verticalAlignment: Text.AlignVCenter - opacity: (hoverHandler.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? 1.0 : 0.0 + opacity: (root.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? 1.0 : 0.0 visible: opacity > 0 - Layout.preferredWidth: (hoverHandler.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? implicitWidth : 0 + Layout.preferredWidth: (root.hovered || calendarPopup.popupOpen) && Cfg.Config.clockExtendEnabled ? implicitWidth : 0 clip: true Behavior on opacity { NumberAnimation { duration: 200 } } @@ -80,32 +68,22 @@ ModuleChip { } } - PopupPanel { + StandardPopup { id: calendarPopup ns: "calendar" chipRoot: root cardWidth: 284 + cardColor: t.calCardBg + cardBorderColor: t.calCardBorder + cardHeight: cardCol.implicitHeight + 28 - PopupCard { - id: card - popupOpen: calendarPopup.popupOpen - isTop: root.isTop - animEnabled: calendarPopup.visible - height: cardCol.implicitHeight + 24 + component MonthNavButton: Rectangle { + id: navBtn + required property int direction - color: root.t.calCardBg - radius: Cfg.Config.popupRadius - border.color: root.t.calCardBorder - border.width: Cfg.Config.popupBorderWidth - layer.enabled: true + width: 26; height: 26; radius: 6 - component MonthNavButton: Rectangle { - id: navBtn - required property int direction - - width: 26; height: 26; radius: 6 - - color: btnMouse.containsMouse + color: btnMouse.containsMouse ? (btnMouse.pressed ? root.t.calArrowBgPress : root.t.calArrowBgHover) : root.t.calArrowBg scale: btnMouse.pressed ? 0.88 : 1.0 @@ -252,7 +230,7 @@ ModuleChip { Repeater { model: ["Mo","Tu","We","Th","Fr","Sa","Su"] Text { - width: (card.width - 32) / 7 + width: (calendarPopup.card.width - 32) / 7 text: modelData; color: root.t.clockPopupDim font.pixelSize: 11; horizontalAlignment: Text.AlignHCenter } @@ -267,7 +245,7 @@ ModuleChip { Repeater { model: 7 delegate: Item { - width: (card.width - 32) / 7; height: 26 + width: (calendarPopup.card.width - 32) / 7; height: 26 readonly property int dayNum: (weekRow.weekIndex * 7 + index) - ((new Date(cal.displayYear, cal.displayMonth, 1).getDay() + 6) % 7) + 1 readonly property bool inMonth: dayNum >= 1 && dayNum <= new Date(cal.displayYear, cal.displayMonth + 1, 0).getDate() readonly property bool isToday: { @@ -337,6 +315,5 @@ ModuleChip { Item { height: 4 } } - } } } diff --git a/bar/modules/Crypto.qml b/bar/modules/Crypto.qml index bf7582f..fc0afcd 100644 --- a/bar/modules/Crypto.qml +++ b/bar/modules/Crypto.qml @@ -12,29 +12,21 @@ ModuleChip { readonly property var cfg: Cfg.Config - readonly property string configPath: - Quickshell.env("HOME") + "/.config/quickshell/config/config.qml" - - Process { - id: cryptoConfigWriter - running: false - onExited: (code) => { - if (code !== 0) - console.warn("[Crypto] Failed to patch config.qml (exit " + code + ")") - } + ConfigWriter { + id: configWriter } width: chipRow.implicitWidth + 24 - height: cfg.moduleHeight radius: panelRadius - color: hoverHandler.hovered ? (t.cryptoBgHover ?? "#15ffffff") : (t.cryptoBg ?? "transparent") - border.color: (hoverHandler.hovered || cryptoPopup.popupOpen) ? (t.cryptoBorderHover ?? t.accent ?? "#ffc19375") : (t.cryptoBorder ?? "transparent") - border.width: borderWidth - - Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } + chipColor: t.cryptoBg + chipColorHovered: t.cryptoBgHover + chipBorderColor: t.cryptoBorder + chipBorderColorHovered: t.cryptoBorderHover + chipHoverEnabled: true + chipTapAction: () => cryptoPopup.toggle() + popupOpen: cryptoPopup.popupOpen + chipAnimWidth: true property var localPairs: [{ coin: "bitcoin", currency: "usd" }] property int activeCoinIndex: 0 @@ -46,18 +38,18 @@ ModuleChip { : "usd" property string localVsCur: "usd" - property int localDecimals: cfg.cryptoDecimals ?? 1 - property int localRefreshSec: cfg.cryptoRefreshSec ?? 60 - property bool localShowIcon: cfg.cryptoShowIcon ?? true + property int localDecimals: cfg.cryptoDecimals + property int localRefreshSec: cfg.cryptoRefreshSec + property bool localShowIcon: cfg.cryptoShowIcon function resolveWithPersistence() { root.localPairs = Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0 ? cfg.cryptoPairs : [{ coin: "bitcoin", currency: "usd" }] root.localVsCur = root.localPairs[0].currency root.displayCurrency = root.localPairs[0].currency root.activeCoinIndex = 0 - root.localDecimals = cfg.cryptoDecimals ?? 1 - root.localRefreshSec = cfg.cryptoRefreshSec ?? 60 - root.localShowIcon = cfg.cryptoShowIcon ?? true + root.localDecimals = cfg.cryptoDecimals + root.localRefreshSec = cfg.cryptoRefreshSec + root.localShowIcon = cfg.cryptoShowIcon } function persistSettings() { @@ -65,30 +57,17 @@ ModuleChip { const decimals = Math.round(root.localDecimals) const refreshSec = Math.round(root.localRefreshSec) const showIcon = root.localShowIcon - const cfgPath = root.configPath const pairsQml = "[" + pairs.map(p => '{ coin: "' + p.coin + '", currency: "' + p.currency + '" }' ).join(", ") + "]" - - const sh = - "CFG=" + JSON.stringify(cfgPath) + "\n" + - "sed -i" + - " -e 's/\\(property int[ ]\\+cryptoDecimals:[ ]\\+\\)[0-9.]\\+/\\1" + decimals.toString() + "/'" + - " -e 's/\\(property int[ ]\\+cryptoRefreshSec:[ ]\\+\\)[0-9.]\\+/\\1" + refreshSec.toString() + "/'" + - " -e 's/\\(property bool[ ]\\+cryptoShowIcon:[ ]\\+\\)\\(true\\|false\\)/\\1" + (showIcon ? "true" : "false") + "/'" + - " \"$CFG\"\n" + - "QS_PAIRS='" + pairsQml + "'\n" + - "awk -v pairs=\"$QS_PAIRS\" '" + - "/property var cryptoPairs:/{print \" property var cryptoPairs: \"pairs;sk=/\\]/?0:1;next}" + - "sk&&/\\]/{sk=0;next}" + - "sk{next}" + - "{print}'" + - " \"$CFG\" > \"${CFG}.tmp\" && mv \"${CFG}.tmp\" \"$CFG\"\n" - - cryptoConfigWriter.command = ["/bin/sh", "-c", sh] - cryptoConfigWriter.running = true + configWriter.writeInts([ + { key: "cryptoDecimals", value: decimals }, + { key: "cryptoRefreshSec", value: refreshSec } + ]) + configWriter.writeBool("cryptoShowIcon", showIcon) + configWriter.writeArray("cryptoPairs", pairsQml) } property real price: -1 @@ -222,12 +201,6 @@ ModuleChip { onLocalRefreshSecChanged: refreshTimer.restart() - HoverHandler { - id: hoverHandler - cursorShape: Qt.PointingHandCursor - } - TapHandler { onTapped: cryptoPopup.toggle() } - RowLayout { id: chipRow anchors.centerIn: parent @@ -250,7 +223,7 @@ ModuleChip { Text { visible: root.localShowIcon text: "󰿤" - color: t.cryptoIcon ?? t.accent ?? "#ffc19375" + color: t.cryptoIcon font.pixelSize: 14 Layout.alignment: Qt.AlignVCenter Layout.rightMargin: 7 @@ -258,14 +231,14 @@ ModuleChip { Text { text: root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": " - color: t.cryptoLabel ?? t.textDim ?? "#997a8996" + color: t.cryptoLabel font.pixelSize: 12 verticalAlignment: Text.AlignVCenter } Text { text: root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price) - color: t.cryptoValue ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoValue font.pixelSize: 13 font.bold: true verticalAlignment: Text.AlignVCenter @@ -274,7 +247,7 @@ ModuleChip { Text { visible: root.price >= 0 text: root.change24h >= 0 ? "▲" : "▼" - color: root.change24h >= 0 ? (t.cryptoUp ?? "#ffb4c9a1") : (t.cryptoDown ?? "#fff38ba8") + color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown) font.pixelSize: 9 verticalAlignment: Text.AlignVCenter Layout.alignment: Qt.AlignVCenter @@ -284,37 +257,19 @@ ModuleChip { } - PopupPanel { + StandardPopup { id: cryptoPopup ns: "crypto" chipRoot: root cardWidth: 300 hasKeyboardFocus: true + cardColor: t.cryptoPopupBg + cardBorderColor: t.cryptoPopupBorder + cardHeight: cardCol.implicitHeight + 24 + layerEnabled: true - function open() { - popupCenterX = root.mapToItem(null, 0, 0).x + root.width / 2 - _doOpen() - } - - PopupCard { - id: card - popupOpen: cryptoPopup.popupOpen - isTop: root.isTop - animEnabled: cryptoPopup.visible - height: cardCol.implicitHeight + 24 - - Behavior on height { NumberAnimation { duration: 220; easing.type: Easing.OutCubic } } - - color: t.cryptoPopupBg ?? t.calCardBg ?? "#cc0c0e12" - radius: Cfg.Config.popupRadius - border.color: t.cryptoPopupBorder ?? t.calCardBorder ?? "transparent" - border.width: Cfg.Config.popupBorderWidth - layer.enabled: true - - property int activeTab: 0 - - ColumnLayout { - id: cardCol + ColumnLayout { + id: cardCol anchors { left: parent.left; right: parent.right; top: parent.top } anchors.margins: 16 anchors.topMargin: 16 @@ -324,7 +279,7 @@ ModuleChip { Layout.fillWidth: true height: 30 radius: 10 - color: t.cryptoFieldBg ?? "#15ffffff" + color: t.cryptoFieldBg RowLayout { anchors.fill: parent @@ -338,16 +293,16 @@ ModuleChip { height: 24 radius: 8 - readonly property bool active: card.activeTab === tabIndex + readonly property bool active: cryptoPopup.activeTab === tabIndex color: active - ? (t.accent ?? "#ffc19375") - : (tm.containsMouse ? (t.cryptoFieldBgFocus ?? "#22ffffff") : "transparent") + ? (t.accent) + : (tm.containsMouse ? (t.cryptoFieldBgFocus) : "transparent") Behavior on color { ColorAnimation { duration: 130 } } Text { anchors.centerIn: parent text: parent.label - color: parent.active ? (t.cryptoTextOnAccent ?? "#ff0c0e12") : (t.cryptoPopupDim ?? t.textDim ?? "#997a8996") + color: parent.active ? (t.cryptoTextOnAccent) : (t.cryptoPopupDim) font.pixelSize: 11 font.bold: parent.active Behavior on color { ColorAnimation { duration: 130 } } @@ -356,7 +311,7 @@ ModuleChip { id: tm anchors.fill: parent; hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: card.activeTab = tabIndex + onClicked: cryptoPopup.activeTab = tabIndex } } @@ -376,8 +331,8 @@ ModuleChip { ColumnLayout { id: priceContent width: tabContainer.width - x: card.activeTab === 0 ? 0 : -tabContainer.width - opacity: card.activeTab === 0 ? 1.0 : 0.0 + x: cryptoPopup.activeTab === 0 ? 0 : -tabContainer.width + opacity: cryptoPopup.activeTab === 0 ? 1.0 : 0.0 Behavior on x { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } } Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } spacing: 10 @@ -387,7 +342,7 @@ ModuleChip { Text { text: "󰿤" - color: t.cryptoIcon ?? t.accent ?? "#ffc19375" + color: t.cryptoIcon font.pixelSize: 22 Layout.alignment: Qt.AlignVCenter } @@ -399,13 +354,13 @@ ModuleChip { Text { text: root.coinSymbol + " / " + root.displayCurrency.toUpperCase() - color: t.cryptoPopupHeader ?? t.clockPopupHeader ?? "#ffc19375" + color: t.cryptoPopupHeader font.pixelSize: 15 font.bold: true } Text { text: root.coinName !== "" ? root.coinName : (root.localCoinId.charAt(0).toUpperCase() + root.localCoinId.slice(1)) - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 } } @@ -413,13 +368,13 @@ ModuleChip { Rectangle { width: badge.implicitWidth + 12 height: 22; radius: 11 - color: root.change24h >= 0 ? (t.cryptoUpBg ?? "#22b4c9a1") : (t.cryptoDownBg ?? "#22f38ba8") + color: root.change24h >= 0 ? (t.cryptoUpBg) : (t.cryptoDownBg) Text { id: badge anchors.centerIn: parent text: (root.change24h >= 0 ? "▲ +" : "▼ ") + root.change24h.toFixed(2) + "%" - color: root.change24h >= 0 ? (t.cryptoUp ?? "#ffb4c9a1") : (t.cryptoDown ?? "#fff38ba8") + color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown) font.pixelSize: 11 font.bold: true } @@ -430,20 +385,20 @@ ModuleChip { Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter text: root.price < 0 ? "Loading…" : root.displayCurrency.toUpperCase() + " " + root.fullPrice(root.price) - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 24 font.bold: true font.family: "monospace" } - Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" } + Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } component StatRow: RowLayout { property string label: "" property string value: "" Layout.fillWidth: true - Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true } - Text { text: value; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"; font.pixelSize: 12; font.bold: true; font.family: "monospace" } + Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true } + Text { text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace" } } StatRow { label: "Rank"; value: root.rank > 0 ? "#" + root.rank : "—" } @@ -455,16 +410,16 @@ ModuleChip { RowLayout { Layout.fillWidth: true - Text { text: "ATH"; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true } + Text { text: "ATH"; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true } Text { text: root.ath > 0 ? root.fullPrice(root.ath) : "—" - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 12; font.bold: true; font.family: "monospace" } Text { visible: root.ath > 0 text: "(" + root.athChange.toFixed(2) + "%)" - color: t.cryptoDown ?? "#fff38ba8" + color: t.cryptoDown font.pixelSize: 11; font.bold: true; font.family: "monospace" } } @@ -477,14 +432,14 @@ ModuleChip { Layout.fillWidth: true Text { text: "24h Range" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 12 Layout.fillWidth: true } Text { visible: root.high24h > root.low24h && root.price >= 0 text: ((root.price - root.low24h) / (root.high24h - root.low24h) * 100).toFixed(1) + "% of range" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 } } @@ -496,15 +451,15 @@ ModuleChip { Rectangle { anchors.fill: parent radius: 3 - color: t.cryptoRangeTrack ?? "#1affffff" + color: t.cryptoRangeTrack } Rectangle { height: parent.height radius: 3 color: root.change24h >= 0 - ? (t.cryptoUp ?? "#ffb4c9a1") - : (t.cryptoDown ?? "#fff38ba8") + ? (t.cryptoUp) + : (t.cryptoDown) width: (root.high24h > root.low24h && root.price >= 0) ? Math.max(radius * 2, Math.min(parent.width, @@ -519,28 +474,28 @@ ModuleChip { Layout.fillWidth: true Text { text: root.low24h > 0 ? root.fullPrice(root.low24h) : "—" - color: t.cryptoDown ?? "#fff38ba8" + color: t.cryptoDown font.pixelSize: 10 font.family: "monospace" } Item { Layout.fillWidth: true } Text { text: root.high24h > 0 ? root.fullPrice(root.high24h) : "—" - color: t.cryptoUp ?? "#ffb4c9a1" + color: t.cryptoUp font.pixelSize: 10 font.family: "monospace" } } } - Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" } + Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } RowLayout { Layout.fillWidth: true Text { text: root.hasError ? "⚠ fetch error" : "Updated " + (root.lastUpdated || "—") - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 Layout.fillWidth: true } @@ -549,7 +504,7 @@ ModuleChip { id: refreshBtn width: 26; height: 26; radius: 8 color: rMouse.containsMouse - ? (rMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) + ? (rMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) : "transparent" Behavior on color { ColorAnimation { duration: 120 } } @@ -557,7 +512,7 @@ ModuleChip { id: refreshIcon anchors.centerIn: parent text: "󰑐" - color: t.cryptoIcon ?? t.accent ?? "#ffc19375" + color: t.cryptoIcon font.pixelSize: 14 RotationAnimator { @@ -585,8 +540,8 @@ ModuleChip { ColumnLayout { id: settingsContent width: tabContainer.width - x: card.activeTab === 1 ? 0 : tabContainer.width - opacity: card.activeTab === 1 ? 1.0 : 0.0 + x: cryptoPopup.activeTab === 1 ? 0 : tabContainer.width + opacity: cryptoPopup.activeTab === 1 ? 1.0 : 0.0 Behavior on x { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } } Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } spacing: 12 @@ -600,7 +555,7 @@ ModuleChip { Text { text: label - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 font.capitalization: Font.AllUppercase } @@ -609,8 +564,8 @@ ModuleChip { Layout.fillWidth: true height: 30 radius: 8 - color: fi.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff") - border.color: fi.activeFocus ? (t.accent ?? "#ffc19375") : "transparent" + color: fi.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg) + border.color: fi.activeFocus ? (t.accent) : "transparent" border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } @@ -618,16 +573,16 @@ ModuleChip { TextInput { id: fi anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 } - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 12 font.family: "monospace" - selectionColor: t.accent ?? "#ffc19375" + selectionColor: t.accent clip: true Text { anchors.fill: parent text: parent.parent.parent.placeholder - color: t.cryptoPlaceholder ?? "#557a8996" + color: t.cryptoPlaceholder font.pixelSize: 12 font.family: "monospace" visible: fi.text === "" && !fi.activeFocus @@ -645,26 +600,26 @@ ModuleChip { signal stepped(int v) Layout.fillWidth: true - Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true } + Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true } Rectangle { width: 24; height: 24; radius: 7 - color: mm.containsMouse ? (mm.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) : (t.cryptoFieldBg ?? "#15ffffff") + color: mm.containsMouse ? (mm.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) : (t.cryptoFieldBg) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" } + Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } MouseArea { id: mm; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: if (value > minVal) stepped(value - 1) } } Rectangle { - width: 54; height: 24; radius: 6; color: t.cryptoFieldBg ?? "#15ffffff" - Text { anchors.centerIn: parent; text: value; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2"; font.pixelSize: 12; font.bold: true; font.family: "monospace" } + width: 54; height: 24; radius: 6; color: t.cryptoFieldBg + Text { anchors.centerIn: parent; text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace" } } Rectangle { width: 24; height: 24; radius: 7 - color: pm.containsMouse ? (pm.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) : (t.cryptoFieldBg ?? "#15ffffff") + color: pm.containsMouse ? (pm.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) : (t.cryptoFieldBg) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" } + Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } MouseArea { id: pm; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: if (value < maxVal) stepped(value + 1) } } } @@ -675,11 +630,11 @@ ModuleChip { signal toggled(bool v) Layout.fillWidth: true - Text { text: label; color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996"; font.pixelSize: 12; Layout.fillWidth: true } + Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true } Rectangle { width: 36; height: 20; radius: 10 - color: checked ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff") + color: checked ? (t.accent) : (t.cryptoFieldBgFocus) Behavior on color { ColorAnimation { duration: 150 } } Rectangle { @@ -699,7 +654,7 @@ ModuleChip { Text { text: "Pairs to cycle" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 font.capitalization: Font.AllUppercase } @@ -718,7 +673,7 @@ ModuleChip { width: 12; z: 2 gradient: Gradient { orientation: Gradient.Horizontal - GradientStop { position: 0.0; color: t.cryptoPopupBg ?? "#cc0c0e12" } + GradientStop { position: 0.0; color: t.cryptoPopupBg } GradientStop { position: 1.0; color: "transparent" } } visible: chipScroll.contentX > 0 @@ -729,7 +684,7 @@ ModuleChip { gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0.0; color: "transparent" } - GradientStop { position: 1.0; color: t.cryptoPopupBg ?? "#cc0c0e12" } + GradientStop { position: 1.0; color: t.cryptoPopupBg } } visible: chipScroll.contentX < chipScroll.contentWidth - chipScroll.width - 1 } @@ -761,7 +716,7 @@ ModuleChip { id: dotSpace anchors.verticalCenter: parent.verticalCenter x: 0; width: 5; height: 5; radius: 3 - color: isActive ? (t.accent ?? "#ffc19375") : "#33ffffff" + color: isActive ? (t.accent) : "#33ffffff" Behavior on color { ColorAnimation { duration: 150 } } } @@ -771,8 +726,8 @@ ModuleChip { x: dotSpace.width + 5 text: (modelData.coin ?? "?") + "/" + (modelData.currency ?? "?").toUpperCase() color: isActive - ? (t.accent ?? "#ffc19375") - : (t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2") + ? (t.accent) + : (t.cryptoPopupText) font.pixelSize: 12 font.bold: isActive font.family: "monospace" @@ -784,12 +739,12 @@ ModuleChip { anchors { right: parent.right verticalCenter: parent.verticalCenter } width: 14; height: 14; radius: 4 - color: rmChipMouse.containsMouse ? (t.cryptoChipRemoveBg ?? "#44f38ba8") : "transparent" + color: rmChipMouse.containsMouse ? (t.cryptoChipRemoveBg) : "transparent" Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent text: "×"; font.pixelSize: 11; font.bold: true - color: t.cryptoDown ?? "#fff38ba8" + color: t.cryptoDown } MouseArea { id: rmChipMouse @@ -818,13 +773,13 @@ ModuleChip { Rectangle { anchors.fill: parent radius: 2 - color: t.cryptoFieldBg ?? "#15ffffff" + color: t.cryptoFieldBg } Rectangle { height: parent.height radius: 2 - color: t.accent ?? "#ffc19375" + color: t.accent opacity: 0.7 readonly property real ratio: chipScroll.width / Math.max(1, chipScroll.contentWidth) @@ -846,7 +801,7 @@ ModuleChip { Text { text: "Coin ID" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 font.capitalization: Font.AllUppercase } @@ -854,8 +809,8 @@ ModuleChip { Rectangle { Layout.fillWidth: true height: 30; radius: 8 - color: addCoinInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff") - border.color: addCoinInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent" + color: addCoinInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg) + border.color: addCoinInput.activeFocus ? (t.accent) : "transparent" border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } @@ -863,15 +818,15 @@ ModuleChip { TextInput { id: addCoinInput anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 } - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 12; font.family: "monospace" - selectionColor: t.accent ?? "#ffc19375" + selectionColor: t.accent clip: true Text { anchors.fill: parent text: "e.g. bitcoin, monero, solana" - color: t.cryptoPlaceholder ?? "#557a8996" + color: t.cryptoPlaceholder font.pixelSize: 12; font.family: "monospace" visible: parent.text === "" && !parent.activeFocus verticalAlignment: Text.AlignVCenter @@ -888,7 +843,7 @@ ModuleChip { Text { text: "Currency" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 font.capitalization: Font.AllUppercase } @@ -900,8 +855,8 @@ ModuleChip { Rectangle { Layout.fillWidth: true height: 30; radius: 8 - color: addCurrencyInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff") - border.color: addCurrencyInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent" + color: addCurrencyInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg) + border.color: addCurrencyInput.activeFocus ? (t.accent) : "transparent" border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } @@ -909,15 +864,15 @@ ModuleChip { TextInput { id: addCurrencyInput anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 7; bottomMargin: 7 } - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 12; font.family: "monospace" - selectionColor: t.accent ?? "#ffc19375" + selectionColor: t.accent clip: true Text { anchors.fill: parent text: "e.g. usd, eur, brl" - color: t.cryptoPlaceholder ?? "#557a8996" + color: t.cryptoPlaceholder font.pixelSize: 12; font.family: "monospace" visible: parent.text === "" && !parent.activeFocus verticalAlignment: Text.AlignVCenter @@ -938,13 +893,13 @@ ModuleChip { Rectangle { width: 30; height: 30; radius: 8 color: addPairMouse.containsMouse - ? (addPairMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) - : (t.cryptoFieldBg ?? "#15ffffff") + ? (addPairMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoFieldBg) Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent; text: "+" font.pixelSize: 14; font.bold: true - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText } MouseArea { id: addPairMouse @@ -978,7 +933,7 @@ ModuleChip { Text { text: "Refresh (seconds)" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 12 Layout.fillWidth: true } @@ -986,10 +941,10 @@ ModuleChip { Rectangle { width: 24; height: 24; radius: 7 color: decMouse.containsMouse - ? (decMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) - : (t.cryptoFieldBg ?? "#15ffffff") + ? (decMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoFieldBg) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" } + Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } MouseArea { id: decMouse anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor @@ -999,8 +954,8 @@ ModuleChip { Rectangle { width: 54; height: 24; radius: 6 - color: refreshInput.activeFocus ? (t.cryptoFieldBgFocus ?? "#22ffffff") : (t.cryptoFieldBg ?? "#15ffffff") - border.color: refreshInput.activeFocus ? (t.accent ?? "#ffc19375") : "transparent" + color: refreshInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg) + border.color: refreshInput.activeFocus ? (t.accent) : "transparent" border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } @@ -1009,11 +964,11 @@ ModuleChip { id: refreshInput anchors { fill: parent; leftMargin: 6; rightMargin: 6; topMargin: 4; bottomMargin: 4 } text: root.localRefreshSec.toString() - color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" + color: t.cryptoPopupText font.pixelSize: 12 font.bold: true font.family: "monospace" - selectionColor: t.accent ?? "#ffc19375" + selectionColor: t.accent horizontalAlignment: TextInput.AlignHCenter inputMethodHints: Qt.ImhDigitsOnly validator: IntValidator { bottom: 10; top: 3600 } @@ -1048,10 +1003,10 @@ ModuleChip { Rectangle { width: 24; height: 24; radius: 7 color: incMouse.containsMouse - ? (incMouse.pressed ? (t.accent ?? "#ffc19375") : (t.cryptoFieldBgFocus ?? "#22ffffff")) - : (t.cryptoFieldBg ?? "#15ffffff") + ? (incMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoFieldBg) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2" } + Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } MouseArea { id: incMouse anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor @@ -1066,7 +1021,7 @@ ModuleChip { onToggled: (v) => root.localShowIcon = v } - Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator ?? "#334a5d6e" } + Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } Rectangle { Layout.fillWidth: true @@ -1074,15 +1029,15 @@ ModuleChip { radius: 9 color: applyMouse.containsMouse ? (applyMouse.pressed - ? Qt.darker(t.accent ?? "#ffc19375", 1.15) - : (t.accent ?? "#ffc19375")) - : (t.cryptoApplyIdleBg ?? "#33c19375") + ? Qt.darker(t.accent, 1.15) + : (t.accent)) + : (t.cryptoApplyIdleBg) Behavior on color { ColorAnimation { duration: 130 } } Text { anchors.centerIn: parent text: "Apply & Refresh" - color: applyMouse.containsMouse ? (t.cryptoTextOnAccent ?? "#ff0c0e12") : (t.cryptoPopupText ?? t.textMain ?? "#ffe8eef2") + color: applyMouse.containsMouse ? (t.cryptoTextOnAccent) : (t.cryptoPopupText) font.pixelSize: 12 font.bold: true Behavior on color { ColorAnimation { duration: 130 } } @@ -1097,7 +1052,7 @@ ModuleChip { root.coinSymbol = root.localCoinId.toUpperCase().slice(0, 4) root.persistSettings() root.fetchPrice() - card.activeTab = 0 + cryptoPopup.activeTab = 0 } } } @@ -1105,7 +1060,7 @@ ModuleChip { Text { Layout.alignment: Qt.AlignHCenter text: "Reset to defaults" - color: t.cryptoPopupDim ?? t.textDim ?? "#997a8996" + color: t.cryptoPopupDim font.pixelSize: 11 font.underline: true @@ -1116,12 +1071,12 @@ ModuleChip { root.localVsCur = "usd" root.displayCurrency = root.localPairs.length > 0 ? root.localPairs[0].currency : "usd" root.activeCoinIndex = 0 - root.localDecimals = cfg.cryptoDecimals ?? 1 - root.localRefreshSec = cfg.cryptoRefreshSec ?? 60 - root.localShowIcon = cfg.cryptoShowIcon ?? true + root.localDecimals = cfg.cryptoDecimals + root.localRefreshSec = cfg.cryptoRefreshSec + root.localShowIcon = cfg.cryptoShowIcon root.persistSettings() root.price = -1 - card.activeTab = 0 + cryptoPopup.activeTab = 0 } } } @@ -1130,6 +1085,5 @@ ModuleChip { } } } - } } } diff --git a/bar/modules/Logo.qml b/bar/modules/Logo.qml index e7a3149..f171fd7 100644 --- a/bar/modules/Logo.qml +++ b/bar/modules/Logo.qml @@ -9,7 +9,7 @@ ModuleChip { property var launcher: null readonly property bool launcherActive: !!launcher && launcher.isOpen - readonly property bool isHovered: hoverHandler.hovered + readonly property bool isHovered: hovered property real spinTarget: 0 @@ -26,16 +26,12 @@ ModuleChip { width: Cfg.Config.logoIconSize * 2 + 4 height: parent.height - color: isHovered ? t.logoBgHover : t.logoBg - radius: panelRadius - - border.color: launcherActive ? t.logoBorderActive : t.logoBorder - border.width: borderWidth - - Behavior on color { ColorAnimation { duration: 250 } } - Behavior on border.color { ColorAnimation { duration: 250 } } - - HoverHandler { id: hoverHandler } + chipColor: t.logoBg + chipColorHovered: t.logoBgHover + chipBorderColor: t.logoBorder + chipBorderColorHovered: t.logoBorderActive + popupOpen: launcherActive + chipAnimDuration: 250 TapHandler { onTapped: { diff --git a/bar/modules/Network.qml b/bar/modules/Network.qml index bd683a9..4b99c63 100644 --- a/bar/modules/Network.qml +++ b/bar/modules/Network.qml @@ -107,16 +107,14 @@ ModuleChip { implicitWidth: chipRow.implicitWidth + 24 height: Cfg.Config.moduleHeight radius: panelRadius - color: chipHover.hovered ? t.netBgHover : t.netBg - border.color: chipHover.hovered ? t.netBorderHover : t.netBorder - border.width: borderWidth - Behavior on implicitWidth { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - - HoverHandler { id: chipHover; cursorShape: Qt.PointingHandCursor } - TapHandler { onTapped: netPopup.toggle() } + chipColor: t.netBg + chipColorHovered: t.netBgHover + chipBorderColor: t.netBorder + chipBorderColorHovered: t.netBorderHover + chipHoverEnabled: true + chipTapAction: () => netPopup.toggle() + chipAnimImplicitWidth: true RowLayout { id: chipRow @@ -150,11 +148,15 @@ ModuleChip { } } - PopupPanel { + StandardPopup { id: netPopup ns: "network" chipRoot: root cardWidth: 310 + cardColor: t.netPopupBg + cardBorderColor: t.netPopupBorder + cardHeight: cardBody.implicitHeight + 28 + layerEnabled: true function open() { root.cancelConnect() @@ -163,20 +165,8 @@ ModuleChip { root.wifiDevice.scannerEnabled = true } - PopupCard { - popupOpen: netPopup.popupOpen - isTop: root.isTop - animEnabled: netPopup.visible - height: cardBody.implicitHeight + 24 - - color: root.t.netPopupBg - radius: Cfg.Config.popupRadius - border.color: root.t.netPopupBorder - border.width: Cfg.Config.popupBorderWidth - layer.enabled: true - - ColumnLayout { - id: cardBody + ColumnLayout { + id: cardBody anchors { left: parent.left right: parent.right @@ -655,6 +645,5 @@ ModuleChip { Item { height: 4 } } - } } } diff --git a/bar/modules/Notifications.qml b/bar/modules/Notifications.qml index aaa6721..a9e311d 100644 --- a/bar/modules/Notifications.qml +++ b/bar/modules/Notifications.qml @@ -16,17 +16,17 @@ ModuleChip { property bool historyOpen: historyPopup.popupOpen width: 35 - height: 40 + height: Cfg.Config.moduleHeight radius: panelRadius - color: hoverHandler.hovered ? t.notifBgHover : t.notifBg + chipColor: t.notifBg + chipColorHovered: t.notifBgHover + popupOpen: historyOpen + border.color: root.doNotDisturb ? t.notifDnd - : ((hoverHandler.hovered || historyOpen) ? t.notifBorderActive : t.notifBorder) - border.width: borderWidth + : ((hovered || historyOpen) ? t.notifBorderActive : t.notifBorder) - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } component NotificationCard: Item { @@ -41,8 +41,8 @@ ModuleChip { property int timeout: 5000 property var t - property var urgencyColor: function(u) { return "#ffffff" } - property var urgencyIcon: function(u) { return "" } + property var urgencyColor + property var urgencyIcon signal dismissed(string toastId) @@ -250,8 +250,8 @@ ModuleChip { property string timeStr: "" property var t - property var urgencyColor: function(u) { return "#ffffff" } - property var urgencyIcon: function(u) { return "" } + property var urgencyColor + property var urgencyIcon signal dismissed(int itemIndex) @@ -334,7 +334,7 @@ ModuleChip { } } - HoverHandler { id: hoverHandler; cursorShape: Qt.PointingHandCursor; onHoveredChanged: if (hovered && Cfg.Config.notificationShakeEnabled) bellRingAnim.start() } + HoverHandler { cursorShape: Qt.PointingHandCursor; onHoveredChanged: if (hovered && Cfg.Config.notificationShakeEnabled) bellRingAnim.start() } TapHandler { onTapped: { if (historyPopup.popupOpen) { @@ -458,7 +458,7 @@ ModuleChip { var finalTimeout = (notif.expireTimeout > 0) ? notif.expireTimeout : cfgTimeout if (!root.doNotDisturb) { - var toastEntry = { toastId, nid: notif.id, appName, summary, body, urgency, timeStr, timeout: finalTimeout } + var toastEntry = { toastId, appName, summary, body, urgency, timeStr, timeout: finalTimeout } if (toastLayer.atBottom) activeToasts.append(toastEntry) else activeToasts.insert(0, toastEntry) if (!root.historyOpen) root.unreadCount++ diff --git a/bar/modules/Stats.qml b/bar/modules/Stats.qml index c7d8e8a..8848a8c 100644 --- a/bar/modules/Stats.qml +++ b/bar/modules/Stats.qml @@ -9,22 +9,14 @@ ModuleChip { id: root width: statsLayout.implicitWidth + 20 - height: Cfg.Config.moduleHeight - color: t.statsBg - radius: panelRadius - border.color: t.statsBorder - border.width: borderWidth + chipColor: t.statsBg + chipBorderColor: t.statsBorder Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } property bool expanded: Cfg.Config.statsStartExpanded - property bool hovered: false - - HoverHandler { - onHoveredChanged: root.hovered = hovered - } TapHandler { onTapped: { diff --git a/bar/modules/Tray.qml b/bar/modules/Tray.qml index ae0fbcd..8a24309 100644 --- a/bar/modules/Tray.qml +++ b/bar/modules/Tray.qml @@ -8,25 +8,17 @@ import Quickshell.Widgets import "../../config" as Cfg import "../../components" -Item { +ModuleChip { id: root - property real panelRadius: Cfg.Config.radius / 2 - property int borderWidth: Cfg.Config.panelBorderWidth - - property var targetScreen: null - property string barSide: "right" - property bool isTop: true - - readonly property var t: Cfg.Config.theme - + property string barSide: "right" property bool expanded: false property bool manuallyExpanded: false readonly property bool effectiveExpanded: expanded || trayMenuPopup.popupOpen - implicitWidth: bgRect.width - implicitHeight: bgRect.height + implicitWidth: mainRow.width + implicitHeight: Cfg.Config.barHeight readonly property color tmBg: t.trayMenuBg readonly property color tmBorder: t.trayMenuBorder @@ -36,47 +28,37 @@ Item { readonly property color tmCheck: t.trayMenuCheck readonly property color tmSeparator: t.trayMenuSeparator - Rectangle { - id: bgRect - anchors.verticalCenter: parent.verticalCenter + chipColor: t.trayBg + chipColorHovered: t.trayBgHover + chipBorderColor: t.trayBorder + chipBorderColorHovered: t.trayBorderHover + popupOpen: trayMenuPopup.popupOpen - height: parent.height - width: mainRow.width - radius: root.panelRadius - - color: bgHover.hovered ? root.t.trayBgHover : root.t.trayBg - border.color: bgHover.hovered ? root.t.trayBorderHover : root.t.trayBorder - border.width: root.borderWidth - - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - - HoverHandler { - id: bgHover - onHoveredChanged: { - if (!root.manuallyExpanded) { - root.expanded = hovered; - } + HoverHandler { + onHoveredChanged: { + if (!root.manuallyExpanded) { + root.expanded = hovered; } } + } - Row { - id: mainRow - anchors.verticalCenter: parent.verticalCenter + Row { + id: mainRow + anchors.verticalCenter: parent.verticalCenter - leftPadding: root.effectiveExpanded && root.barSide === "right" ? 8 : 0 - rightPadding: root.effectiveExpanded && root.barSide === "left" ? 8 : 0 + leftPadding: root.effectiveExpanded && root.barSide === "right" ? 8 : 0 + rightPadding: root.effectiveExpanded && root.barSide === "left" ? 8 : 0 - Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } - Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } - layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft - spacing: root.effectiveExpanded ? 4 : 0 + layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft + spacing: root.effectiveExpanded ? 4 : 0 - Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } + Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } - Item { - id: toggleArea + Item { + id: toggleArea width: Cfg.Config.trayToggleSize height: Cfg.Config.trayToggleSize z: 10 @@ -149,8 +131,8 @@ Item { } } } - } } + } diff --git a/bar/modules/Volume.qml b/bar/modules/Volume.qml index bf96574..5214b34 100644 --- a/bar/modules/Volume.qml +++ b/bar/modules/Volume.qml @@ -14,41 +14,24 @@ ModuleChip { property int outputMaxVolume: Cfg.Config.volumeOutputMax property int inputMaxVolume: Cfg.Config.volumeInputMax - // Path to config.qml — using HOME to avoid Qt.resolvedUrl ambiguity - readonly property string configPath: - Quickshell.env("HOME") + "/.config/quickshell/config/config.qml" - - // Process that patches volumeOutputMax / volumeInputMax in config.qml - Process { - id: volConfigWriter - running: false - onExited: (code) => { - if (code !== 0) - console.warn("[Volume] Failed to patch config.qml (exit " + code + ")") - } + ConfigWriter { + id: configWriter } - // Debounce: write to disk 800 ms after the last limit change Timer { id: saveDebounce interval: 800 repeat: false onTriggered: { - const outMax = Math.round(root.outputMaxVolume).toString() - const inMax = Math.round(root.inputMaxVolume).toString() - const cfgPath = root.configPath - const sh = - "sed -i" + - " -e 's/\\(property int[ ]\\+volumeOutputMax:[ ]\\+\\)[0-9.]\\+/\\1" + outMax + "/'" + - " -e 's/\\(property int[ ]\\+volumeInputMax:[ ]\\+\\)[0-9.]\\+/\\1" + inMax + "/'" + - " " + JSON.stringify(cfgPath) - volConfigWriter.command = ["/bin/sh", "-c", sh] - volConfigWriter.running = true + configWriter.writeInts([ + { key: "volumeOutputMax", value: root.outputMaxVolume }, + { key: "volumeInputMax", value: root.inputMaxVolume } + ]) } } - onOutputMaxVolumeChanged: { if (root.outputMaxVolume >= 10) saveDebounce.restart() } - onInputMaxVolumeChanged: { if (root.inputMaxVolume >= 10) saveDebounce.restart() } + onOutputMaxVolumeChanged: saveDebounce.restart() + onInputMaxVolumeChanged: saveDebounce.restart() readonly property var sink: Pipewire.defaultAudioSink readonly property var source: Pipewire.defaultAudioSource @@ -115,24 +98,22 @@ ModuleChip { } width: chipLayout.implicitWidth + 15 - height: Cfg.Config.moduleHeight radius: panelRadius - color: hoverHandler.hovered ? t.volBgHover : t.volBg - border.color: (hoverHandler.hovered || volumePopup.popupOpen) ? t.volBorderHover : t.volBorder - border.width: borderWidth + chipColor: t.volBg + chipColorHovered: t.volBgHover + chipBorderColor: t.volBorder + chipBorderColorHovered: t.volBorderHover + chipHoverEnabled: true + chipTapAction: () => volumePopup.toggle() + popupOpen: volumePopup.popupOpen - Behavior on color { ColorAnimation { duration: 150 } } - Behavior on border.color { ColorAnimation { duration: 150 } } - - HoverHandler { - id: hoverHandler - cursorShape: Qt.PointingHandCursor + HoverHandler { + cursorShape: Qt.PointingHandCursor onHoveredChanged: { if (hovered && Cfg.Config.volumeShakeEnabled) shakeAnim.restart() } } - TapHandler { onTapped: volumePopup.toggle() } SequentialAnimation { id: shakeAnim @@ -159,29 +140,21 @@ ModuleChip { } } - PopupPanel { + StandardPopup { id: volumePopup ns: "volume" chipRoot: root cardWidth: Cfg.Config.volumePopupWidth + cardColor: t.volPopupBg + cardBorderColor: t.volPopupBorder + cardHeight: popupCol.implicitHeight + 34 - PopupCard { - popupOpen: volumePopup.popupOpen - isTop: root.isTop - animEnabled: volumePopup.visible - height: popupCol.implicitHeight + 32 - - radius: Cfg.Config.popupRadius - color: root.t.volPopupBg - border.color: root.t.volPopupBorder - border.width: Cfg.Config.popupBorderWidth - - ColumnLayout { - id: popupCol - anchors { left: parent.left; right: parent.right; top: parent.top } - anchors.margins: 16 - anchors.topMargin: 18 - spacing: 14 + ColumnLayout { + id: popupCol + anchors { left: parent.left; right: parent.right; top: parent.top } + anchors.margins: 16 + anchors.topMargin: 18 + spacing: 14 VolumeSection { id: outputSection @@ -272,7 +245,6 @@ ModuleChip { } Item { height: 2 } } - } } component VolumeSection: ColumnLayout { diff --git a/bar/modules/Workspace.qml b/bar/modules/Workspace.qml index fe0d84d..6e35366 100644 --- a/bar/modules/Workspace.qml +++ b/bar/modules/Workspace.qml @@ -10,10 +10,8 @@ ModuleChip { width: workspaceLayout.implicitWidth + 24 height: Cfg.Config.moduleHeight - color: t.wsPanelBg - radius: panelRadius - border.color: t.wsPanelBorder - border.width: borderWidth + chipColor: t.wsPanelBg + chipBorderColor: t.wsPanelBorder RowLayout { id: workspaceLayout diff --git a/components/ConfigWriter.qml b/components/ConfigWriter.qml new file mode 100644 index 0000000..897031c --- /dev/null +++ b/components/ConfigWriter.qml @@ -0,0 +1,68 @@ +import QtQuick +import Quickshell +import Quickshell.Io + +Item { + id: root + + property string configPath: + Quickshell.env("HOME") + "/.config/quickshell/config/config.qml" + + Process { + id: writerProc + running: false + onExited: (code) => { + if (code !== 0) + console.warn("[ConfigWriter] Patch failed (exit " + code + ")") + } + property string _name: "ConfigWriter" + } + + function writeInt(key, value) { + const n = Math.round(value).toString() + const sh = "sed -i" + + " -e 's/\\(property int[[:space:]]\\+\\b" + key + "\\b:[ ]*\\)[0-9.]\\+/\\1" + n + "/'" + + " " + JSON.stringify(root.configPath) + writerProc.command = ["/bin/sh", "-c", sh] + writerProc.running = true + } + + function writeBool(key, value) { + const v = value ? "true" : "false" + const sh = "sed -i" + + " -e 's/\\(property bool[[:space:]]\\+\\b" + key + "\\b:[ ]*\\)\\(true\\|false\\)/\\1" + v + "/'" + + " " + JSON.stringify(root.configPath) + writerProc.command = ["/bin/sh", "-c", sh] + writerProc.running = true + } + + function writeInts(pairs) { + let args = "" + for (let i = 0; i < pairs.length; i++) { + const n = Math.round(pairs[i].value).toString() + args += " -e 's/\\(property int[[:space:]]\\+\\b" + pairs[i].key + "\\b:[ ]*\\)[0-9.]\\+/\\1" + n + "/'" + } + const sh = "sed -i" + args + " " + JSON.stringify(root.configPath) + writerProc.command = ["/bin/sh", "-c", sh] + writerProc.running = true + } + + function writeArray(key, pairsQml) { + const sh = + "CFG=" + JSON.stringify(root.configPath) + "\n" + + "QS_PAIRS='" + pairsQml + "'\n" + + "awk -v pairs=\"$QS_PAIRS\" '" + + "/^[[:space:]]*property var[[:space:]]+" + key + ":[[:space:]]/{print \" property var " + key + ": \"pairs;sk=/\\]/?0:1;next}" + + "sk&&/\\]/{sk=0;next}" + + "sk{next}" + + "{print}'" + + " \"$CFG\" > \"${CFG}.tmp\" && mv \"${CFG}.tmp\" \"$CFG\"\n" + writerProc.command = ["/bin/sh", "-c", sh] + writerProc.running = true + } + + function writeScript(sh) { + writerProc.command = ["/bin/sh", "-c", sh] + writerProc.running = true + } +} diff --git a/components/HoverButton.qml b/components/HoverButton.qml new file mode 100644 index 0000000..57941f0 --- /dev/null +++ b/components/HoverButton.qml @@ -0,0 +1,34 @@ +import QtQuick + +Rectangle { + id: root + + property color idleColor: "transparent" + property color hoverColor: "transparent" + property color pressColor: "transparent" + property color borderIdleColor: "transparent" + property color borderHoverColor: "transparent" + property real pressScale: 0.97 + property int animDuration: 150 + + readonly property bool hovered: _hover.hovered + readonly property bool pressed: _tap.pressed + + signal clicked() + + color: pressed ? pressColor : (hovered ? hoverColor : idleColor) + border.color: hovered ? borderHoverColor : borderIdleColor + + scale: pressed ? pressScale : 1.0 + + Behavior on color { ColorAnimation { duration: root.animDuration } } + Behavior on border.color { ColorAnimation { duration: root.animDuration } } + Behavior on scale { NumberAnimation { duration: 100; easing.type: Easing.OutQuad } } + + HoverHandler { id: _hover } + TapHandler { + id: _tap + cursorShape: Qt.PointingHandCursor + onTapped: root.clicked() + } +} diff --git a/components/ModuleChip.qml b/components/ModuleChip.qml index d5b02bf..9d2873f 100644 --- a/components/ModuleChip.qml +++ b/components/ModuleChip.qml @@ -13,4 +13,44 @@ Rectangle { readonly property var t: Cfg.Config.theme property bool moduleEnabled: true + + property bool hovered: false + property bool popupOpen: false + + property color chipColor: "transparent" + property color chipColorHovered: "transparent" + property color chipBorderColor: "transparent" + property color chipBorderColorHovered: "transparent" + property bool chipHoverEnabled: false + property var chipTapAction: null + + property int chipAnimDuration: 150 + property bool chipAnimWidth: false + property bool chipAnimImplicitWidth: false + + radius: panelRadius + color: hovered ? chipColorHovered : chipColor + border.color: (hovered || popupOpen) ? chipBorderColorHovered : chipBorderColor + border.width: borderWidth + + Behavior on color { ColorAnimation { duration: chip.chipAnimDuration } } + Behavior on border.color { ColorAnimation { duration: chip.chipAnimDuration } } + Behavior on width { + NumberAnimation { duration: 250; easing.type: Easing.OutCubic } + enabled: chipAnimWidth + } + Behavior on implicitWidth { + NumberAnimation { duration: 250; easing.type: Easing.OutCubic } + enabled: chipAnimImplicitWidth + } + + HoverHandler { + id: hoverHandler + cursorShape: chipHoverEnabled ? Qt.PointingHandCursor : Qt.ArrowCursor + onHoveredChanged: chip.hovered = hovered + } + + TapHandler { + onTapped: if (chip.chipTapAction) chip.chipTapAction() + } } diff --git a/components/PopupCard.qml b/components/PopupCard.qml index 939295b..2cb6182 100644 --- a/components/PopupCard.qml +++ b/components/PopupCard.qml @@ -7,6 +7,7 @@ Rectangle { required property bool popupOpen required property bool isTop property bool animEnabled: true + property bool showShadow: false width: parent.width @@ -27,6 +28,18 @@ Rectangle { opacity: popupOpen ? 1.0 : 0.0 Behavior on opacity { NumberAnimation { duration: 200 } } + Rectangle { + visible: card.showShadow && card.popupOpen + anchors.fill: parent + anchors.margins: -3 + radius: card.radius + 3 + color: "transparent" + border.color: Qt.rgba(0, 0, 0, 0.35) + border.width: 6 + opacity: card.showShadow && card.popupOpen ? 0.6 : 0 + Behavior on opacity { NumberAnimation { duration: 200 } } + } + default property alias _popupCardContent: _content.data Item { diff --git a/components/StandardPopup.qml b/components/StandardPopup.qml new file mode 100644 index 0000000..f0df119 --- /dev/null +++ b/components/StandardPopup.qml @@ -0,0 +1,31 @@ +import QtQuick +import "../config" as Cfg + +PopupPanel { + id: popup + + property color cardColor: "transparent" + property color cardBorderColor: "transparent" + property alias cardHeight: card.height + property alias showShadow: card.showShadow + property bool layerEnabled: false + property alias hasKeyboardFocus: popup.hasKeyboardFocus + property alias card: card + property int activeTab: 0 + + default property alias popupContent: card._popupCardContent + + PopupCard { + id: card + popupOpen: popup.popupOpen + isTop: popup.chipRoot ? popup.chipRoot.isTop : true + animEnabled: popup.visible + color: popup.cardColor + radius: Cfg.Config.popupRadius + border.color: popup.cardBorderColor + border.width: Cfg.Config.popupBorderWidth + layer.enabled: popup.layerEnabled + + Behavior on height { NumberAnimation { duration: 220; easing.type: Easing.OutCubic } } + } +} diff --git a/components/TimezoneProvider.qml b/components/TimezoneProvider.qml index b845cee..4635c08 100644 --- a/components/TimezoneProvider.qml +++ b/components/TimezoneProvider.qml @@ -29,7 +29,7 @@ Item { } Timer { - interval: 1800000 + interval: 300000 running: root.tz !== "" repeat: true onTriggered: tzProc.running = true diff --git a/config/config.qml b/config/config.qml index dcae508..853a7a7 100644 --- a/config/config.qml +++ b/config/config.qml @@ -19,7 +19,7 @@ QtObject { // ──────────────────────────────────────────────────────────────────────── // ── Position & Dimensions ───────────────────────────────────────────────── - property string barPosition: "bottom" + property string barPosition: "top" property int barHeight: 35 property int margin: 20 property int radius: 26 @@ -49,7 +49,7 @@ QtObject { // ── Timezone (IANA name, e.g. "America/New_York", "Europe/London") ────────── // Leave empty to use the system timezone. - property string timezone: none + property string timezone: "America/New_York" // Date format used in the clock popup and background date widget. // "MDY" → month/day/year (e.g. May 14, 2026) @@ -76,7 +76,7 @@ QtObject { property int volumeSliderHeight: 2 property int volumeHandleSize: 20 property int volumePopupWidth: 280 - property int volumeOutputMax: 140 + property int volumeOutputMax: 190 property int volumeInputMax: 200 @@ -127,7 +127,7 @@ QtObject { // // This list is the *default*; pairs can be added/removed live in the // Settings popup and those changes are persisted across restarts. - property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "solana", currency: "brl" }] + property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }] // ── Compact label decimals ──────────────────────────────────────────────── // 0 → "80k" diff --git a/polkit/Polkit.qml b/polkit/Polkit.qml index 69de663..ee2f201 100644 --- a/polkit/Polkit.qml +++ b/polkit/Polkit.qml @@ -4,6 +4,7 @@ import Quickshell.Wayland import Quickshell.Services.Polkit import "../config" as Cfg +import "../components" Item { @@ -115,37 +116,18 @@ Item { color: t.polkitOverlayBg } - component DialogButton: Rectangle { + component DialogButton: HoverButton { property string label property int labelWeight: Font.Normal - property color bgColor - property color bgHoverColor - property color borderColor - property color borderHoverColor property color labelColor signal tapped() width: (parent.width - 12) / 2 height: 44 radius: 10 - - HoverHandler { id: hover } - - color: hover.hovered ? bgHoverColor : bgColor - border.color: hover.hovered ? borderHoverColor : borderColor border.width: 1 - Behavior on color { ColorAnimation { duration: 200 } } - Behavior on border.color { ColorAnimation { duration: 200 } } - - scale: pressHandler.pressed ? 0.97 : 1.0 - Behavior on scale { NumberAnimation { duration: 100; easing.type: Easing.OutQuad } } - - TapHandler { - id: pressHandler - cursorShape: Qt.PointingHandCursor - onTapped: parent.tapped() - } + onClicked: tapped() Text { anchors.centerIn: parent @@ -464,20 +446,22 @@ Item { label: "Authenticate" labelWeight: Font.Medium labelColor: t.polkitAuthText - bgColor: t.polkitAuthBg - bgHoverColor: t.polkitAuthBgHover - borderColor: t.polkitAuthBg + idleColor: t.polkitAuthBg + hoverColor: t.polkitAuthBgHover + borderIdleColor: t.polkitAuthBg borderHoverColor: t.polkitAuthBgHover + animDuration: 200 onTapped: root.submitAuth() } DialogButton { label: "Cancel" labelColor: t.polkitCancelText - bgColor: t.polkitCancelBg - bgHoverColor: t.polkitCancelBgHover - borderColor: t.polkitCancelBorder + idleColor: t.polkitCancelBg + hoverColor: t.polkitCancelBgHover + borderIdleColor: t.polkitCancelBorder borderHoverColor: t.polkitCancelBgHover + animDuration: 200 onTapped: overlay.cancelAndClose() } } diff --git a/shell.qml b/shell.qml index 70132b2..4e2d26f 100644 --- a/shell.qml +++ b/shell.qml @@ -21,7 +21,7 @@ ShellRoot { readonly property bool isTop: Cfg.Config.barPosition === "top" property color frameBackground: Cfg.Config.theme.bgFrame - property color frameBorderColor: Cfg.Config.theme.frameBorder ?? Cfg.Config.theme.borderPopup + property color frameBorderColor: Cfg.Config.theme.frameBorder // ── Polkit Agent ───────────────────────────────────────────────────────── Loader { diff --git a/widgets/bgDate/BgDate.qml b/widgets/bgDate/BgDate.qml index 1a9a20b..d18a74f 100644 --- a/widgets/bgDate/BgDate.qml +++ b/widgets/bgDate/BgDate.qml @@ -14,6 +14,7 @@ PanelWindow { anchors { top: true; bottom: true; left: true; right: true } WlrLayershell.layer: WlrLayer.Background + WlrLayershell.namespace: "main-shell-bgDate" WlrLayershell.exclusiveZone: -1 mask: Region {}