diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-04 15:15:25 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-04 15:15:25 -0500 |
| commit | 4c9730a6e88f1f0173d9712311f65f348d211f4e (patch) | |
| tree | 7489f342778f1fda640b6dce90d4a567db71c14f | |
| parent | 1067005467d66bbaae5853d2cacda749fb72cbcc (diff) | |
| download | chime-4c9730a6e88f1f0173d9712311f65f348d211f4e.tar.gz chime-4c9730a6e88f1f0173d9712311f65f348d211f4e.zip | |
Bundle multiple day-wide events into a single notification
When all-day event alert times trigger, multiple events (overdue tasks,
birthdays, holidays) previously fired individual notifications — one
sound and one popup each. With 8-10 events this was overwhelming.
Now multiple day-wide events are bundled into a single notification
with all messages joined by newlines. Single events still notify
normally without bundling.
| -rw-r--r-- | chime.el | 12 | ||||
| -rw-r--r-- | tests/test-chime-process-notifications.el | 57 |
2 files changed, 67 insertions, 2 deletions
@@ -1720,8 +1720,16 @@ Handles both regular event notifications and day-wide alerts." (-uniq)) 'chime--notify) (when (chime-current-time-is-day-wide-time) - (mapc 'chime--notify - (chime-day-wide-notifications events)))) + (let ((day-wide (chime-day-wide-notifications events))) + (when day-wide + (if (= 1 (length day-wide)) + ;; Single event: send as normal notification + (chime--notify (car day-wide)) + ;; Multiple events: bundle into one notification, one sound + (let* ((messages (mapcar #'car day-wide)) + (body (mapconcat #'identity messages "\n")) + (title (format "%d day-wide events" (length day-wide)))) + (chime--notify (cons body 'medium)))))))) (defun chime--maybe-warn-persistent-failures () "Warn user if async failures have reached the threshold. diff --git a/tests/test-chime-process-notifications.el b/tests/test-chime-process-notifications.el index eddec02..181f146 100644 --- a/tests/test-chime-process-notifications.el +++ b/tests/test-chime-process-notifications.el @@ -327,5 +327,62 @@ REFACTORED: Uses dynamic timestamps and with-test-time" (should (>= notify-count 1)))))) (test-chime-process-notifications-teardown))) +;;; Day-wide bundling + +(ert-deftest test-chime-process-notifications-day-wide-multiple-events-single-notify () + "Multiple day-wide events should produce a single bundled notification, +not one notification per event." + (test-chime-process-notifications-setup) + (unwind-protect + (let* ((now (test-time-today-at 8 0)) + (notify-count 0) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) + (setq notify-count (1+ notify-count)) + (push msg notify-messages))) + ((symbol-function 'chime-current-time-is-day-wide-time) + (lambda () t)) + ((symbol-function 'chime-day-wide-notifications) + (lambda (events) + (list (cons "Blake's birthday is today" 'medium) + (cons "Holiday: Memorial Day is today" 'medium) + (cons "Submit expense report is due or scheduled today" 'medium))))) + (chime--process-notifications '()) + ;; Should fire exactly ONE notification for all day-wide events + (should (= 1 notify-count)) + ;; The single notification body should contain all event messages + (let ((body (caar notify-messages))) + (should (string-match-p "Blake's birthday" body)) + (should (string-match-p "Memorial Day" body)) + (should (string-match-p "expense report" body)))))) + (test-chime-process-notifications-teardown))) + +(ert-deftest test-chime-process-notifications-day-wide-single-event-no-bundling () + "A single day-wide event should produce a normal notification, not bundled." + (test-chime-process-notifications-setup) + (unwind-protect + (let* ((now (test-time-today-at 8 0)) + (notify-count 0) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) + (setq notify-count (1+ notify-count)) + (push msg notify-messages))) + ((symbol-function 'chime-current-time-is-day-wide-time) + (lambda () t)) + ((symbol-function 'chime-day-wide-notifications) + (lambda (events) + (list (cons "Blake's birthday is today" 'medium))))) + (chime--process-notifications '()) + ;; Single event: still one notification + (should (= 1 notify-count)) + ;; Should be the plain message, not wrapped in a bundle + (let ((body (caar notify-messages))) + (should (string= "Blake's birthday is today" body)))))) + (test-chime-process-notifications-teardown))) + (provide 'test-chime-process-notifications) ;;; test-chime-process-notifications.el ends here |
