mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-13 14:36:32 -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:
@@ -695,6 +695,7 @@ Singleton {
|
||||
property int notificationTimeoutNormal: 5000
|
||||
property int notificationTimeoutCritical: 0
|
||||
property bool notificationCompactMode: false
|
||||
property bool notificationShowTimeoutBar: false
|
||||
property bool notificationDedupeEnabled: true
|
||||
property int notificationPopupPosition: SettingsData.Position.Top
|
||||
property int notificationAnimationSpeed: SettingsData.AnimationSpeed.Short
|
||||
|
||||
@@ -406,6 +406,7 @@ var SPEC = {
|
||||
notificationTimeoutNormal: { def: 5000 },
|
||||
notificationTimeoutCritical: { def: 0 },
|
||||
notificationCompactMode: { def: false },
|
||||
notificationShowTimeoutBar: { def: false },
|
||||
notificationDedupeEnabled: { def: true },
|
||||
notificationPopupPosition: { def: 0 },
|
||||
notificationAnimationSpeed: { def: 1 },
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -273,6 +273,15 @@ Item {
|
||||
onToggled: checked => SettingsData.set("notificationCompactMode", checked)
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
settingKey: "notificationShowTimeoutBar"
|
||||
tags: ["notification", "timeout", "progress", "bar", "timer", "countdown"]
|
||||
text: I18n.tr("Timeout Progress Bar")
|
||||
description: I18n.tr("Show a bar that drains as the popup's auto-dismiss timer runs")
|
||||
checked: SettingsData.notificationShowTimeoutBar
|
||||
onToggled: checked => SettingsData.set("notificationShowTimeoutBar", checked)
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
settingKey: "notificationDedupeEnabled"
|
||||
tags: ["notification", "duplicate", "dedupe", "stack", "coalesce", "repeat"]
|
||||
|
||||
Reference in New Issue
Block a user