aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chime.el58
-rw-r--r--tests/test-integration-chime-mode.el45
2 files changed, 92 insertions, 11 deletions
diff --git a/chime.el b/chime.el
index 49e6428..ae1078c 100644
--- a/chime.el
+++ b/chime.el
@@ -1763,7 +1763,8 @@ Does nothing if a check is already in progress."
(chime--debug-log-async-error (cdr events)))
(chime--log-silently "Chime: Async error: %s"
(error-message-string (cdr events)))
- (chime--maybe-warn-persistent-failures))
+ (chime--maybe-warn-persistent-failures)
+ (chime--set-modeline-error-state "Event check failed — check *Messages* buffer"))
;; Success - process events normally
(setq chime--consecutive-async-failures 0)
(when (featurep 'chime-debug)
@@ -1776,7 +1777,8 @@ Does nothing if a check is already in progress."
(chime--debug-log-async-error err))
(chime--log-silently "Chime: Error processing events: %s"
(error-message-string err))
- (chime--maybe-warn-persistent-failures)))))))))
+ (chime--maybe-warn-persistent-failures)
+ (chime--set-modeline-error-state "Event check failed — check *Messages* buffer")))))))))
(defun chime--log-silently (format-string &rest args)
"Append formatted message to *Messages* buffer without echoing.
@@ -1799,17 +1801,25 @@ Returns nil if validation failed and check should be skipped."
(progn
(setq chime--validation-retry-count (1+ chime--validation-retry-count))
(if (> chime--validation-retry-count chime-validation-max-retries)
- (let ((errors (cl-remove-if-not (lambda (i) (eq (car i) :error)) issues)))
- (chime--log-silently "Chime: Configuration validation failed with %d error(s) after %d retries:"
- (length errors)
- chime--validation-retry-count)
- (dolist (err errors)
- (chime--log-silently "")
- (chime--log-silently "ERROR: %s" (cadr err)))
- (message "Chime: Configuration errors detected (see *Messages* buffer for details)"))
+ (progn
+ (let ((errors (cl-remove-if-not (lambda (i) (eq (car i) :error)) issues)))
+ (chime--log-silently "Chime: Configuration validation failed with %d error(s) after %d retries:"
+ (length errors)
+ chime--validation-retry-count)
+ (dolist (err errors)
+ (chime--log-silently "")
+ (chime--log-silently "ERROR: %s" (cadr err))))
+ (message "Chime: Configuration errors detected (see *Messages* buffer for details)")
+ ;; Update modeline tooltip to show error state
+ (chime--set-modeline-error-state "Configuration error — check *Messages* buffer"))
(message "Chime: Waiting for org-agenda-files to load... (attempt %d/%d)"
chime--validation-retry-count
- chime-validation-max-retries))
+ chime-validation-max-retries)
+ ;; Update modeline tooltip to show waiting state
+ (chime--set-modeline-error-state
+ (format "Waiting for org-agenda-files... (attempt %d/%d)"
+ chime--validation-retry-count
+ chime-validation-max-retries)))
nil)
(setq chime--validation-done t)
(setq chime--validation-retry-count 0)
@@ -1848,6 +1858,30 @@ Does nothing if a check is already in progress in the background."
(lambda (events)
(chime--update-modeline events))))
+(defun chime--set-modeline-error-state (error-message)
+ "Update modeline icon tooltip to show ERROR-MESSAGE.
+Keeps the icon visible so the user knows chime is running but has a problem."
+ (when chime-modeline-no-events-text
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line mouse-1] #'chime--open-calendar-url)
+ (setq chime-modeline-string
+ (propertize chime-modeline-no-events-text
+ 'help-echo (format "Chime: %s" error-message)
+ 'mouse-face 'mode-line-highlight
+ 'local-map map))
+ (force-mode-line-update t))))
+
+(defun chime--make-initial-modeline-string ()
+ "Create the initial modeline string shown before the first check completes.
+Uses `chime-modeline-no-events-text' with a loading tooltip."
+ (when chime-modeline-no-events-text
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line mouse-1] #'chime--open-calendar-url)
+ (propertize chime-modeline-no-events-text
+ 'help-echo "Chime: waiting for first event check..."
+ 'mouse-face 'mode-line-highlight
+ 'local-map map))))
+
;;;###autoload
(define-minor-mode chime-mode
"Toggle org notifications globally.
@@ -1861,6 +1895,8 @@ if needed."
;; Add modeline string to global-mode-string
(when (and chime-enable-modeline
(> chime-modeline-lookahead-minutes 0))
+ ;; Set icon immediately so the user sees chime is active
+ (setq chime-modeline-string (chime--make-initial-modeline-string))
(if global-mode-string
(add-to-list 'global-mode-string 'chime-modeline-string 'append)
(setq global-mode-string '("" chime-modeline-string)))))
diff --git a/tests/test-integration-chime-mode.el b/tests/test-integration-chime-mode.el
index 0f19330..69ad176 100644
--- a/tests/test-integration-chime-mode.el
+++ b/tests/test-integration-chime-mode.el
@@ -65,5 +65,50 @@ and set it to nil."
;; Timer should be nil after disable
(should (null chime--timer))))
+(ert-deftest test-integration-chime-mode-enable-sets-modeline-string-immediately ()
+ "Enabling chime-mode should set chime-modeline-string to a non-nil value
+immediately, before the first async check completes."
+ (let ((chime-enable-modeline t)
+ (chime-modeline-lookahead-minutes 120)
+ (chime-modeline-no-events-text " ⏰"))
+ (unwind-protect
+ (progn
+ (chime-mode 1)
+ ;; Should be non-nil right away, not after startup delay
+ (should chime-modeline-string)
+ (should (stringp chime-modeline-string)))
+ (chime-mode -1))))
+
+(ert-deftest test-integration-chime-mode-enable-immediate-string-has-tooltip ()
+ "The immediate modeline string should have a help-echo tooltip."
+ (let ((chime-enable-modeline t)
+ (chime-modeline-lookahead-minutes 120)
+ (chime-modeline-no-events-text " ⏰"))
+ (unwind-protect
+ (progn
+ (chime-mode 1)
+ (should (get-text-property 0 'help-echo chime-modeline-string)))
+ (chime-mode -1))))
+
+(ert-deftest test-integration-chime-mode-validation-failure-keeps-icon-visible ()
+ "When validation fails, modeline should still show the icon with error info
+in the tooltip, not go blank."
+ (let ((chime-enable-modeline t)
+ (chime-modeline-lookahead-minutes 120)
+ (chime-modeline-no-events-text " ⏰")
+ (org-agenda-files nil)
+ (chime--validation-done nil)
+ (chime--validation-retry-count 0)
+ (chime-validation-max-retries 0))
+ (unwind-protect
+ (progn
+ (chime-mode 1)
+ ;; Force a check that will fail validation
+ (chime-check)
+ ;; Icon should still be visible, not nil
+ (should chime-modeline-string)
+ (should (stringp chime-modeline-string)))
+ (chime-mode -1))))
+
(provide 'test-integration-chime-mode)
;;; test-integration-chime-mode.el ends here