Show a notification the sender updated, instead of the version it replaced

A client that updates a notification through replaces_id does not produce a
second onNotification: Quickshell writes the new content onto the Notification
object the shell is already holding. The card draws a snapshot copied out of
that object — deliberately, since a live QObject in a ListModel role becomes a
dangling pointer the moment the server destroys it — so the toast kept showing
the superseded text, and archived it to history when it left the screen. A
Slack thread that updates in place read as stuck.

Every property the card draws is now watched on the notification we hold, and
a change rewrites both the model row and the file the popup was persisted
under. The file name is that popup's identity, so the rewrite lands in place:
a shell restart restores the version last shown, and so does the copy that
reaches history.

The countdown starts over when the content changes. New text arriving a second
before the toast was due to expire deserves a full look, not the remainder of
the clock the text it replaced had nearly run through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-12 00:58:14 -07:00
co-authored by Claude Opus 5
parent ab57ad65fd
commit cd84583b56
3 changed files with 143 additions and 0 deletions
@@ -92,6 +92,17 @@ function snapshotOf(notification, timestamp) {
}
}
// A client updating a notification through replaces_id keeps the identity of
// the popup it took over: the file name is the timestamp and id the popup was
// first persisted under, and the restore, replace and archive paths all key
// off that name. Only what the card draws comes from the updated object.
function replacementSnapshot(notification, originalId, timestamp) {
var updated = snapshotOf(notification, timestamp)
updated.id = originalId
updated.originalId = originalId
return updated
}
function historyEntry(value, normalUrgency) {
var e = value || {}
return {
@@ -265,6 +276,7 @@ if (typeof module !== "undefined") {
execFromHints: execFromHints,
shouldRenderCompactGlyph: shouldRenderCompactGlyph,
snapshotOf: snapshotOf,
replacementSnapshot: replacementSnapshot,
historyEntry: historyEntry,
parseSettings: parseSettings,
historyRows: historyRows,