aboutsummaryrefslogtreecommitdiffstats
path: root/notifications
AgeCommit message (Collapse)AuthorFilesLines
4 daysnotifications: quiet mode silences notification sounds tooDanilo M.2-1/+17
Quiet muted only the Claude and opencode hooks, which play their own sounds and check the flag themselves. With notification sounds it now means no sound at all while the balloons still show, so the balloon player reads status.quiet the way Notify reads status.dnd, without instantiating Status. A per-app quiet list was left out: the mute list already covers an app that should make no sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysnotifications: write gsettings only when the theme changedDanilo M.1-1/+2
From the final review. Every save ran gsettings set, so saving a timeout on a first run, with no soundTheme in the file, silently reset a system theme set elsewhere to freedesktop; the page now writes it only when the draft's theme differs from the file's, and flags any other mismatch as before. An exit code outside 0-3, a save killed mid-run, now reads as an error rather than a partial success. The player's comment no longer claims the balloon's expiry check, which it does not need. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysdocs: notification soundsDanilo M.1-0/+9
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysnotifications: play a sound for a new balloonDanilo M.1-0/+34
pw-play, once per new or replaced notification, only when the balloon would show: the drawer, snooze, mute and DND that withhold the balloon silence it too. A restart records the queue without playing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysdocs: the notification settings page and config.jsonDanilo M.1-3/+9
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysnotifications: place, mute and DND balloons from config.jsonDanilo M.2-9/+13
Screen and corner come from the shared config. Mute and the DND rule go through NotifyConfig.withheld, so the settings page's node check covers the same decision the balloon makes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 daysnotifications: resolve notifyd's config.json in a shared libraryDanilo M.1-0/+1
One resolver for both shells and the settings page, with the defaults that reproduce today's behaviour, and the mute/DND decision beside it so the node check covers it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysName the project Keystone, and move its paths and namespacesDanilo M.2-2/+2
The repository had no name of its own, only the framework's. It is now Keystone, in the README, AGENTS.md, the settings window, notes commit messages, calctl's PRODID and the user page's User-Agent. Its files move off quickshell's name too: ~/.config/quickshell/greetings -> ~/.config/keystone/ ~/.config/quickshell/obs-scene-icons.json -> ~/.config/keystone/ $XDG_STATE_HOME/quickshell/desktop.json -> $XDG_STATE_HOME/keystone/ ~/.config/quickshell is Quickshell's own default config directory (a bare qs loads its shell.qml), so sharing it was a collision rather than a home. There is no fallback to the old paths: the files are moved once. The layer namespaces become keystone-*, and the Hyprland blur rules in hypr-theme are renamed to match in the same change. A running shell keeps its old namespaces until restarted. Left alone: the retired standalone mail and vm shells' namespaces, which their READMEs keep as history; Quickshell's own app id, binary and process name; and the repository directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06feat(notifications): window border on the balloonsDanilo M.2-5/+95
The balloons now wear the Hyprland window border: 2px, the udt gradient read from ~/.cache/udt/udt-border.lua (the file look_and_feel.lua reads, watched so a wallpaper change follows), rotating, with the windows' corners. A Rectangle border takes one colour and its radius is circular, while the windows use rounding 15 at rounding_power 4, a superellipse. So the body and the border are both drawn by a Shape from an SVG path whose corners are the cubic fit to |x|^4 + |y|^4 = 1, and the border is a ring filled odd-even, which keeps the translucent body from showing the gradient through. One angle drives every balloon, so they turn together, and the animation runs only while the stack is mapped. Hyprland's borderangle (speed 30) reads as 3s a turn, which looked slow on a balloon that size, so the turn is 1.5s, tuned by eye. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29feat(notifications): render bodies as MarkdownDanilo M.1-1/+1
Balloon and drawer bodies switch from RichText to Qt's MarkdownText (CommonMark plus GitHub extensions). Raw HTML still goes through Qt's HTML importer, so body-markup senders keep working. Markdown images fetch their destination the same way an <img> does, which the existing sanitize filter would miss since it only inspects tags. sanitize now escapes every "![" so the syntax renders as literal text, local or remote; parsing CommonMark destinations and reference definitions to allow local ones is not worth the grammar. Verified in the shell log: before the filter reached the running shell, a test body fetched https://example.org/a.png; after, a second one did not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27fix(notifications): theme the action picker with udtDanilo M.1-1/+2
notify-actions.sh called rofi with no -theme, so clicking a notification that carries actions opened rofi in its stock theme instead of the udt one every other menu uses. Pass ~/.config/rofi/udt/menu.rasi, the small fixed-options layout the screenshot and notes menus already use. menu.rasi shows only the listview, so the "Notification" prompt and the filter input are not drawn; a notification's actions are few enough that picking from the list is enough. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-15fix(notifications): check every img src and uncache previewDanilo M.1-0/+1
The sanitizer matched the first \bsrc anywhere in the tag, so a data-src="file:///tmp/decoy" before a remote src won the match and kept the whole tag while Qt, which ignores data-src, fetched the remote image. Scan every src assignment in the tag and keep it only if all of them are local. Also set cache: false on the balloon preview, since the daemon overwrites the same path on a replace and QQuickPixmapCache keys on URL, so a replaced notification could show the previous image.
2026-09-15feat(notifications): strip remote inline image sourcesDanilo M.1-1/+1
A notification is untrusted input. Inline <img> now renders only for local sources; an http(s) source is removed before the RichText body is shown, so a remote sender cannot make the shell fetch a URL. The row and the balloon share the one sanitizer in the Notify singleton.
2026-09-15feat(notifications): draw the content image in the balloonDanilo M.1-1/+25
The daemon now publishes an image path; the balloon shows it below the text, scaled to the balloon width with a 240px cap. A daemon without the field leaves it hidden, so the renderer and the daemon can ship in either order.
2026-09-15feat(desktop): make the drawer notifications readableDanilo M.1-4/+5
Each row shows when the notification appeared ("Sep 15 14:32", from created), sits on its own rounded card with space between rows instead of reading as one list, and uses the balloon's 16/18/16 sizing rather than 13/11. The close target grows to a 32px hit area in the row and the balloon, since a 20px box was hard to hit.
2026-09-15fix(notifications): apply final review fixesDanilo M.2-2/+1
Mirror the balloon's right-click close-all on the drawer row: the spec says the gestures are identical in both forms, and a right-click on a row previously did nothing. The right-button branch precedes the live guard so it behaves the same on history rows. Stop importing the Status singleton into the notification shell. Referencing it instantiated it, and its onPresentationChanged writes status.dnd and runs breaktimer.sh, so a read-only consumer was writing state and shelling out on every presentation toggle, and doubled the dndBeforePresentation race. Notify now reads "/run/user/<uid>/status.dnd" directly through a FileView, the same convention as the notifyd files; a missing file means off. AGENTS.md named Drawer.qml as the drawer's reserved space; it is desktop/NotificationList.qml.
2026-09-15docs(notifications): document the renderers and record the trapsDanilo M.1-0/+8
The daemon is a separate process and the files are the interface; suppression lives in the balloon shell so the drawer can list what DND held back; and the drawer flag is what stops a notification appearing as both a balloon and a row.
2026-09-15feat(notifications): add the rofi action pickerDanilo M.1-0/+40
The renderer passes the action labels and keys as arguments, so the picker parses no JSON; a chosen label maps to its key and runs notifyctl action.
2026-09-15fix(notifications): map the balloon window from the queue, not layoutDanilo M.1-3/+8
Deriving the window's visible from column.implicitHeight deadlocked it: a hidden window stops polishing, Column computes implicitHeight during polish, so once the column was empty the window never re-mapped and no later balloon could show, including at startup where the queue arrives asynchronously after the window is already hidden. The binding now reads Notify.queue membership, which a property binding re-evaluates whether or not the window is mapped, so a later notification re-maps it. Expired entries left in the queue keep a zero-height window mapped, which is harmless.
2026-09-15fix(notifications): keep the balloon model stable across ticksDanilo M.2-14/+31
The Repeater model was a fresh filter of Notify.queue on every 250ms tick because the filter read now, so Qt Quick recreated every balloon delegate four times a second, reloading icons and resetting hover. Model is now Notify.queue itself, and each balloon drops itself at expiry through its own visible binding, driven by the shared tick. Removing required from the balloon's properties is part of the same fix: a required property makes QML create the delegate in its own context, where modelData and index are undefined, so notification: modelData silently arrived undefined once a live queue item was actually drawn.
2026-09-15feat(notifications): add the balloon shellDanilo M.7-0/+244
Reads the daemon's queue through the Notify singleton and draws a balloon per live notification, bottom-right of DP-1 over conky. Suppression is here, not in the daemon: dnd withholds low and normal, snooze withholds all, and the drawer still lists them.