diff --git a/modules/HoverPanel.qml b/modules/HoverPanel.qml index 59f1e44..59192fa 100644 --- a/modules/HoverPanel.qml +++ b/modules/HoverPanel.qml @@ -43,16 +43,14 @@ PanelWindow { property bool _winVisible: false property bool _pinned: false - property real _dragStartX: 0 - // When pinned, only the header bar receives input — content passes through to desktop. - // Full header width allows drag-to-reposition; pin button tap is within that region too. + // When pinned, only the pin button area receives input — everything else passes through mask: _pinned ? _pinMask : null property Region _pinMask: Region { - x: panelContainer.x + x: panelContainer.x + panelContainer.width - 28 y: 0 - width: panelContainer.width + width: 28 height: 24 } @@ -192,21 +190,12 @@ PanelWindow { } } - // Popup mode: click-outside dismiss. - // TapHandler fires for all taps; position check skips taps inside panelContainer. - // Gated on !_grace so spurious events during the 400ms opening window don't dismiss. - Item { + // Popup mode: click-outside dismiss (declared first = lowest z = below content) + MouseArea { anchors.fill: parent visible: root.popupMode - - TapHandler { - enabled: !root._grace - onTapped: { - const p = point.position; - if (p.x < panelContainer.x || p.x > panelContainer.x + panelContainer.width || p.y < panelContainer.y || p.y > panelContainer.y + panelContainer.height) - root.dismiss(); - } - } + enabled: root.popupMode + onClicked: root.dismiss() } M.PopupBackground { @@ -226,6 +215,13 @@ PanelWindow { height: _panelColumn.height opacity: 0 + // Popup mode: eat clicks on panel background so outer dismiss doesn't fire + MouseArea { + anchors.fill: parent + visible: root.popupMode + enabled: root.popupMode + } + HoverHandler { enabled: !root.popupMode && !root._pinned onHoveredChanged: if (!root.popupMode && !root._pinned) @@ -239,31 +235,10 @@ PanelWindow { // Header row: title + action buttons + pin — shown in hover mode always, // and in popup mode when a title or actions are provided. Item { - id: _headerItem visible: !root.popupMode || root.panelTitle !== "" || root.titleActionsComponent !== null width: parent.width height: 24 - // Drag header to reposition panel while pinned (hover mode only) - DragHandler { - enabled: root._pinned && !root.popupMode - yAxis.enabled: false - onActiveChanged: if (active) - root._dragStartX = panelContainer.x - onActiveTranslationChanged: { - if (active) { - const sw = root.screen?.width ?? 1920; - panelContainer.x = Math.max(0, Math.min(root._dragStartX + activeTranslation.x, sw - root.contentWidth)); - } - } - } - - // Show move cursor on header when pinned - HoverHandler { - enabled: root._pinned && !root.popupMode - cursorShape: Qt.SizeHorCursor - } - Text { visible: root.panelTitle !== "" anchors.left: parent.left diff --git a/modules/Mpris.qml b/modules/Mpris.qml index f783643..0ffbbb7 100644 --- a/modules/Mpris.qml +++ b/modules/Mpris.qml @@ -122,7 +122,7 @@ M.BarSection { panelTitle: "Now Playing" contentWidth: 280 - // Album art — always 1:1, crossfades on session switch + // Album art — always 1:1 Item { width: parent.width height: width @@ -133,71 +133,22 @@ M.BarSection { color: M.Theme.base02 } - // Outgoing art — snaps to current opacity, then fades out - Image { - id: _artImgPrev - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - asynchronous: true - opacity: 0 - - NumberAnimation { - id: _prevFadeOut - target: _artImgPrev - property: "opacity" - to: 0 - duration: 300 - easing.type: Easing.InOutCubic - } - } - - // Incoming art — fades in once loaded Image { id: _artImg anchors.fill: parent fillMode: Image.PreserveAspectCrop + visible: _hasArt asynchronous: true - opacity: 0 + source: root._cachedArt property bool _hasArt: false - - onStatusChanged: { - if (status === Image.Ready && source !== "") { - _hasArt = true; - _artFadeIn.start(); - _prevFadeOut.start(); - } else if (status === Image.Error) { - _hasArt = false; - } - } - - NumberAnimation { - id: _artFadeIn - target: _artImg - property: "opacity" - to: 1 - duration: 300 - easing.type: Easing.InOutCubic - } - + onStatusChanged: if (status === Image.Ready) + _hasArt = true Connections { target: root function on_CachedArtChanged() { - if (!root._cachedArt) { - _artFadeIn.stop(); - _prevFadeOut.stop(); + if (!root._cachedArt) _artImg._hasArt = false; - _artImg.opacity = 0; - _artImgPrev.opacity = 0; - _artImg.source = ""; - } else if (root._cachedArt !== _artImg.source) { - _prevFadeOut.stop(); - _artFadeIn.stop(); - _artImgPrev.source = _artImg.source; - _artImgPrev.opacity = _artImg.opacity; - _artImg.opacity = 0; - _artImg.source = root._cachedArt; - } } } } @@ -236,7 +187,7 @@ M.BarSection { anchors.right: parent.right anchors.bottom: parent.bottom height: 40 - visible: _artImg._hasArt + visible: _artImg.visible gradient: Gradient { GradientStop { position: 0 @@ -255,7 +206,7 @@ M.BarSection { color: M.Theme.base04 font.pixelSize: 28 font.family: M.Theme.iconFontFamily - visible: !_artImg._hasArt + visible: _artImg.status !== Image.Ready } } diff --git a/modules/NotifService.qml b/modules/NotifService.qml index 77b829e..0591eae 100644 --- a/modules/NotifService.qml +++ b/modules/NotifService.qml @@ -90,13 +90,7 @@ QtObject { }); root._byId[item.id] = item; - root.list = [item, ...root.list].sort((a, b) => { - const aU = a.urgency === NotificationUrgency.Critical ? 1 : 0; - const bU = b.urgency === NotificationUrgency.Critical ? 1 : 0; - if (aU !== bU) - return bU - aU; - return b.time - a.time; - }); + root.list = [item, ...root.list]; // Trim excess popups const max = M.Modules.notifications.maxPopups || 4; @@ -180,13 +174,6 @@ QtObject { root._byId[item.id] = item; root.list.push(item); } - root.list.sort((a, b) => { - const aU = a.urgency === NotificationUrgency.Critical ? 1 : 0; - const bU = b.urgency === NotificationUrgency.Critical ? 1 : 0; - if (aU !== bU) - return bU - aU; - return b.time - a.time; - }); root._changed(); } catch (e) {} } diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 33cbc0f..c2cb1a1 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -152,11 +152,6 @@ in default = 15; description = "Battery percentage for critical notification and blink."; }; - poweralertd = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Enable poweralertd for battery/power event notifications. Set to false to disable."; - }; }; weather = moduleOpt "weather" ( (intervalOpt 3600000) @@ -239,10 +234,6 @@ in } ]; - services.poweralertd.enable = lib.mkIf ( - cfg.modules.battery.enable && cfg.modules.battery.poweralertd - ) (lib.mkDefault true); - systemd.user.services.nova-shell = lib.mkIf cfg.systemd.enable { Unit = { Description = "nova-shell Quickshell bar";