From f0193eedd3729bbc591f1b7bc9313db9e7a83260 Mon Sep 17 00:00:00 2001 From: rope Date: Wed, 17 Jun 2026 14:56:49 +0100 Subject: [PATCH] quickshell: round album art, full-width notifications with app icon + image preview - album art uses ClippingRectangle so the image follows the radius - NotifContent gains an app icon + name header - notifications move to a full-width card spanning both panes, each item showing the notification image preview when present Co-Authored-By: Claude Opus 4.8 --- settings/quickshell.nix | 193 ++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 75 deletions(-) diff --git a/settings/quickshell.nix b/settings/quickshell.nix index c81d3a6..09956ab 100644 --- a/settings/quickshell.nix +++ b/settings/quickshell.nix @@ -475,6 +475,29 @@ in signal actionInvoked() spacing: 2 + // App header: icon + name of the sending app, when known. + Row { + width: parent.width + spacing: 4 + visible: _nc.notif && (_nc.notif.appName !== "" || _appIcon.source != "") + Image { + id: _appIcon + width: 14; height: 14 + sourceSize.width: 14; sourceSize.height: 14 + anchors.verticalCenter: parent.verticalCenter + source: _nc.notif && _nc.notif.appIcon ? Quickshell.iconPath(_nc.notif.appIcon, true) : "" + visible: source != "" + } + SText { + anchors.verticalCenter: parent.verticalCenter + text: _nc.notif ? _nc.notif.appName : "" + color: Theme.base04 + font.pixelSize: 10 + elide: Text.ElideRight + width: parent.width - (_appIcon.visible ? 18 : 0) + } + } + SText { width: parent.width text: _nc.notif ? (_nc.notif.summary || _nc.notif.appName) : "" @@ -2145,7 +2168,7 @@ in // ceil: Text metrics give fractional sizes; fractional rect // edges render as soft 2px lines fullWidth: Math.ceil(calRow.width) + 24 - fullHeight: Math.ceil(calRow.height) + 24 + fullHeight: Math.ceil(calRow.height + 8 + notifCard.height) + 24 // Month being viewed; reset to today when the popup opens // (via the setup function passed to bar.toggleDropdown). @@ -2430,12 +2453,11 @@ in width: parent.width spacing: 12 - Rectangle { + ClippingRectangle { width: 128; height: 128 radius: Theme.radiusSmall anchors.verticalCenter: parent.verticalCenter color: Theme.base02 - clip: true SIcon { anchors.centerIn: parent visible: albumArt.status !== Image.Ready @@ -2548,85 +2570,106 @@ in } } - // Notifications card - Card { + } + } + + // ── Notifications: spans both columns, below the panes ── + Card { + id: notifCard + anchors.top: calRow.bottom + anchors.topMargin: 8 + anchors.horizontalCenter: parent.horizontalCenter + width: calRow.width + opacity: calRow.opacity + cardSpacing: 6 + + Item { + width: parent.width + height: 20 + SText { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + text: "Notifications" + font.weight: Font.Medium + } + SText { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: bar.notifServer.trackedNotifications.values.length > 0 ? "Clear all" : "" + color: Theme.base04 + font.pixelSize: 11 + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + let notifs = bar.notifServer.trackedNotifications.values; + for (let i = notifs.length - 1; i >= 0; i--) { + notifs[i].dismiss(); + } + } + } + } + } + + SText { + visible: bar.notifServer.trackedNotifications.values.length === 0 + text: "No notifications" + color: Theme.base03 + font.pixelSize: 11 + anchors.horizontalCenter: parent.horizontalCenter + } + + Repeater { + model: bar.notifServer.trackedNotifications + + Rectangle { + id: notifItem + required property var modelData width: parent.width - cardSpacing: 6 + height: Math.max(notifPreview.visible ? 48 : 0, ncBody.height) + 16 + radius: Theme.radiusSmall + color: Theme.base02 - Item { - width: parent.width - height: 20 - - SText { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - text: "Notifications" - font.weight: Font.Medium - } - - SText { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - text: bar.notifServer.trackedNotifications.values.length > 0 ? "Clear all" : "" - color: Theme.base04 - font.pixelSize: 11 - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - let notifs = bar.notifServer.trackedNotifications.values; - for (let i = notifs.length - 1; i >= 0; i--) { - notifs[i].dismiss(); - } - } - } + // Image preview (album art, screenshot thumb…) + ClippingRectangle { + id: notifPreview + visible: notifItem.modelData.image != "" + anchors.left: parent.left + anchors.top: parent.top + anchors.margins: 8 + width: 48; height: 48 + radius: Theme.radiusTiny + color: Theme.base01 + Image { + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: notifItem.modelData.image } } - SText { - visible: bar.notifServer.trackedNotifications.values.length === 0 - text: "No notifications" - color: Theme.base03 - font.pixelSize: 11 - anchors.horizontalCenter: parent.horizontalCenter + NotifContent { + id: ncBody + notif: notifItem.modelData + anchors.left: notifPreview.visible ? notifPreview.right : parent.left + anchors.right: dismissBtn.left + anchors.top: parent.top + anchors.margins: 8 } - Repeater { - model: bar.notifServer.trackedNotifications - - Rectangle { - id: notifItem - required property var modelData - width: parent.width - height: ncBody.height + 16 - radius: Theme.radiusSmall - color: Theme.base02 - - NotifContent { - id: ncBody - notif: notifItem.modelData - anchors.left: parent.left - anchors.right: dismissBtn.left - anchors.top: parent.top - anchors.margins: 8 - } - - SIcon { - id: dismissBtn - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: 8 - text: "close" - color: dismissMa.containsMouse ? Theme.base05 : Theme.base03 - font.pixelSize: 15 - MouseArea { - id: dismissMa - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: notifItem.modelData.dismiss() - } - } + SIcon { + id: dismissBtn + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 8 + text: "close" + color: dismissMa.containsMouse ? Theme.base05 : Theme.base03 + font.pixelSize: 15 + MouseArea { + id: dismissMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: notifItem.modelData.dismiss() } } }