1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-15 07:35:20 -04:00

feat(notifications): add opt-in timeout progress bar on popups (#2587)

Adds a thin bar pinned to the bottom of the notification card that drains
full->empty over the auto-dismiss timer, as a visual countdown to
dismissal. Opt-in via notificationShowTimeoutBar (default off), with a
toggle in Settings > Notifications. Shown for any timed notification
(timer.interval > 0, including timed criticals); inset by the corner
radius, and frozen while hovered or during the exit animation. Plain
Rectangle - no offscreen textures or shader passes. A Connections on the
timer resets the bar on every (re)start, including the in-place restart
on a deduped notification.

Co-authored-by: bogdan-velicu <hydrotech074@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bogdan Velicu
2026-06-11 22:22:22 +03:00
committed by GitHub
parent 5483303714
commit 573785d4ce
4 changed files with 56 additions and 0 deletions
@@ -727,6 +727,51 @@ PanelWindow {
}
}
// Timeout progress bar: drains as the dismiss timer runs; inset by
// the corner radius and frozen while hovered or during exit.
Rectangle {
id: timeoutBar
readonly property bool active: SettingsData.notificationShowTimeoutBar && notificationData && notificationData.timer && notificationData.timer.interval > 0
property real progress: 1
readonly property real surfaceRadius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
visible: active && progress > 0
anchors.left: parent.left
anchors.leftMargin: surfaceRadius
anchors.bottom: parent.bottom
width: Math.max(0, parent.width - surfaceRadius * 2) * progress
height: Math.max(2, Theme.snap(3, win.dpr))
radius: height / 2
z: 50
opacity: 0.9
color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.error : Theme.primary
NumberAnimation {
id: progressAnim
target: timeoutBar
property: "progress"
from: 1
to: 0
duration: (notificationData && notificationData.timer && notificationData.timer.interval > 0) ? notificationData.timer.interval : 5000
running: timeoutBar.active && notificationData && notificationData.timer && notificationData.timer.running && !win.exiting
easing.type: Easing.Linear
}
// Reset to full on every (re)start, including an in-place
// restart on a deduped notification (running stays true, so the
// bound animation alone wouldn't re-fire).
Connections {
target: timeoutBar.active ? notificationData.timer : null
function onRunningChanged() {
if (notificationData && notificationData.timer && notificationData.timer.running && !win.exiting) {
timeoutBar.progress = 1;
progressAnim.restart();
}
}
}
}
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true