diff options
| author | Raúl Benencia <id@rbenencia.name> | 2025-12-29 14:39:52 -0300 |
|---|---|---|
| committer | Raúl Benencia <id@rbenencia.name> | 2025-12-29 14:47:46 -0300 |
| commit | 246d25c6d57667b5d254262e0bf7188dfa6dbb6b (patch) | |
| tree | ae4a3b02425e3dcf35ac501971483c58a08c4311 | |
| parent | 4a59cbc0765c30f632ccd7bc5c73f72e2d840d11 (diff) | |
Cap notifications
| -rw-r--r-- | org-tempus.el | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/org-tempus.el b/org-tempus.el index f3014e4..bcbf3f6 100644 --- a/org-tempus.el +++ b/org-tempus.el @@ -72,6 +72,16 @@ :type 'integer :group 'org-tempus) +(defcustom org-tempus-notification-cooldown-seconds 600 + "Minimum seconds between break and idle notifications." + :type 'integer + :group 'org-tempus) + +(defcustom org-tempus-notification-max-count 3 + "Maximum number of break or idle notifications." + :type 'integer + :group 'org-tempus) + (defcustom org-tempus-break-threshold-seconds 10800 "Maximum break seconds to display when no task is clocked in." :type 'integer @@ -115,11 +125,6 @@ Set to 0 to disable auto clock-out." :type 'integer :group 'org-tempus) -(defcustom org-tempus-idle-notify-cooldown-seconds 600 - "Minimum seconds between idle notifications." - :type 'integer - :group 'org-tempus) - (defcustom org-tempus-idle-provider 'emacs "Provider used to query idle time. Known providers are `emacs' (activity inside Emacs), @@ -171,14 +176,11 @@ Known providers are `emacs' (activity inside Emacs), (defvar org-tempus--idle-active-streak 0 "Accumulated seconds of continuous active user presence.") -(defvar org-tempus--last-idle-notify-time nil - "Last time an idle notification was sent.") - (defvar org-tempus--session-start-time nil "Internal session start time as a value returned by `current-time'.") -(defvar org-tempus--session-threshold-notified nil - "Internal flag indicating the session threshold notification was sent.") +(defvar org-tempus--notification-state nil + "Plist storing notification state for notifications.") (defun org-tempus--hide-org-mode-line () "Hide the stock Org mode line indicator while Org Tempus is active." @@ -246,16 +248,42 @@ Known providers are `emacs' (activity inside Emacs), (defun org-tempus-reset-session () "Reset the current session timer." (interactive) - (setq org-tempus--session-threshold-notified nil) + (org-tempus--reset-notification-state) (if (org-clock-is-active) (setq org-tempus--session-start-time (current-time)) (setq org-tempus--session-start-time nil)) (org-tempus--update-mode-line) (message "Org Tempus session reset.")) +(defun org-tempus--reset-notification-state () + "Reset notification state." + (setq org-tempus--notification-state nil)) + +(defun org-tempus--notification-allowed-p () + "Return non-nil when a notification can be sent." + (let* ((state org-tempus--notification-state) + (count (plist-get state :count)) + (last (plist-get state :last-time)) + (max-count org-tempus-notification-max-count) + (cooldown org-tempus-notification-cooldown-seconds) + (since (and last + (float-time (time-subtract (current-time) last))))) + (and (> max-count 0) + (< (or count 0) max-count) + (or (not last) (>= since cooldown))))) + +(defun org-tempus--record-notification () + "Record a notification." + (let* ((state org-tempus--notification-state) + (count (1+ (or (plist-get state :count) 0)))) + (setq org-tempus--notification-state + (plist-put (plist-put (or state nil) :count count) + :last-time (current-time))))) + (defun org-tempus--update-session-start () "Update session start time. Keep a short task change within the same session." (when org-clock-start-time + (org-tempus--reset-notification-state) (let* ((last-out org-clock-out-time) (gap (and last-out (float-time (time-subtract org-clock-start-time last-out))))) @@ -265,7 +293,7 @@ Known providers are `emacs' (activity inside Emacs), (<= gap org-tempus-session-gap-seconds)) (or org-tempus--session-start-time org-clock-start-time) (progn - (setq org-tempus--session-threshold-notified nil) + (org-tempus--reset-notification-state) org-clock-start-time)))))) (defun org-tempus--current-session-duration () @@ -282,8 +310,8 @@ A session does not reset when switching tasks within (defun org-tempus--maybe-notify-session-threshold (session-seconds) "Send a one-time notification when SESSION-SECONDS crosses threshold." (when (and (>= session-seconds org-tempus-session-threshold-seconds) - (not org-tempus--session-threshold-notified)) - (setq org-tempus--session-threshold-notified t) + (org-tempus--notification-allowed-p)) + (org-tempus--record-notification) (let ((msg (format "Org Tempus session reached %s" (org-duration-from-minutes (/ session-seconds 60.0))))) @@ -366,7 +394,7 @@ A session does not reset when switching tasks within (seconds-to-time idle-seconds))) (org-clock-out nil t)) (setq org-tempus--session-start-time nil) - (setq org-tempus--session-threshold-notified nil) + (org-tempus--reset-notification-state) (org-tempus--update-mode-line) (org-tempus--notify (format "Auto clocked out after %s idle." @@ -379,15 +407,10 @@ A session does not reset when switching tasks within (when (and (>= org-tempus--idle-active-streak org-tempus-idle-active-streak-seconds) (not (org-clock-is-active))) - (let* ((now (current-time)) - (since (and org-tempus--last-idle-notify-time - (float-time - (time-subtract now org-tempus--last-idle-notify-time))))) - (when (or (not since) - (>= since org-tempus-idle-notify-cooldown-seconds)) - (setq org-tempus--last-idle-notify-time now) - (org-tempus--notify - "You seem active but no task is clocked in."))))))) + (when (org-tempus--notification-allowed-p) + (org-tempus--record-notification) + (org-tempus--notify + "You seem active but no task is clocked in.")))))) (defun org-tempus--update-mode-line () "Update the Org Tempus mode line indicator." @@ -450,8 +473,10 @@ A session does not reset when switching tasks within org-tempus-update-interval #'org-tempus--update-mode-line)) (add-hook 'org-clock-in-hook #'org-tempus--update-session-start) + (add-hook 'org-clock-in-hook #'org-tempus--reset-notification-state) (add-hook 'org-clock-in-hook #'org-tempus--update-mode-line t) (add-hook 'org-clock-in-hook #'org-tempus--hide-org-mode-line t) + (add-hook 'org-clock-out-hook #'org-tempus--reset-notification-state) (add-hook 'org-clock-out-hook #'org-tempus--update-mode-line) (add-hook 'org-clock-out-hook #'org-tempus--hide-org-mode-line) (advice-add 'org-clock-update-mode-line :after #'org-tempus--maybe-hide-org-mode-line) @@ -506,10 +531,12 @@ A session does not reset when switching tasks within (cancel-timer org-tempus--idle-timer)) (setq org-tempus--idle-timer nil) (remove-hook 'org-clock-in-hook #'org-tempus--update-session-start) + (remove-hook 'org-clock-in-hook #'org-tempus--reset-notification-state) (remove-hook 'org-clock-in-hook #'org-tempus--update-mode-line) (remove-hook 'org-clock-in-hook #'org-tempus--hide-org-mode-line) (remove-hook 'org-clock-out-hook #'org-tempus--hide-org-mode-line) (remove-hook 'org-clock-out-hook #'org-tempus--update-mode-line) + (remove-hook 'org-clock-out-hook #'org-tempus--reset-notification-state) (advice-remove 'org-clock-update-mode-line #'org-tempus--maybe-hide-org-mode-line))) (provide 'org-tempus) |
