fix: show notifications and unread count for SSE messages arriving when chat closed
Three gaps caused messages received via SSE to be invisible when the conversation buffer wasn't already open: 1. Echo-area notification (noise-receive.el): when an SSE message arrives and the conversation buffer isn't in a visible window, show "[Noise] <name>" in the echo area. 2. Modeline unread counter (noise.el): the noise-mode lighter now shows Noise[N] for N unread messages via a lightweight SUM aggregation across all conversations. 3. Auto-refresh hook (noise-conversation.el): a window-buffer-change-functions hook re-renders *signal:* buffers when they become visible, covering direct C-x b switches. Also adds regression test: noise-receive-sse-stores-then-open-shows-message — store via SSE handler with no buffer open, then open and verify.
This commit is contained in:
@@ -245,5 +245,19 @@ NAME is the contact typing; ACTION is signal-cli's STARTED or STOPPED."
|
|||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(noise-chat-list--render))))
|
(noise-chat-list--render))))
|
||||||
|
|
||||||
|
;;; Auto-refresh when conversation buffers become visible
|
||||||
|
|
||||||
|
(defun noise-conversation--on-buffer-visible (_frame)
|
||||||
|
"Refresh any stale `*signal:*' conversation buffer that just became visible."
|
||||||
|
(dolist (window (window-list nil 'never (selected-frame)))
|
||||||
|
(when-let ((buf (window-buffer window)))
|
||||||
|
(when (and (string-prefix-p "*signal:" (buffer-name buf))
|
||||||
|
(not (string= "*signal*" (buffer-name buf))))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(when (derived-mode-p 'noise-conversation-mode)
|
||||||
|
(noise-conversation--render)))))))
|
||||||
|
|
||||||
|
(add-hook 'window-buffer-change-functions #'noise-conversation--on-buffer-visible)
|
||||||
|
|
||||||
(provide 'noise-conversation)
|
(provide 'noise-conversation)
|
||||||
;;; noise-conversation.el ends here
|
;;; noise-conversation.el ends here
|
||||||
|
|||||||
+10
-1
@@ -44,13 +44,22 @@ Returns the number of new messages stored."
|
|||||||
(message "Received %d new message%s" new (if (= new 1) "" "s")))
|
(message "Received %d new message%s" new (if (= new 1) "" "s")))
|
||||||
new))
|
new))
|
||||||
|
|
||||||
|
(defun noise-receive--announce-message (conv-id)
|
||||||
|
"Show a brief echo-area notification for a new message in CONV-ID."
|
||||||
|
(let* ((conv (noise-db-get-conversation conv-id))
|
||||||
|
(name (if conv (or (gethash "name" conv) conv-id) conv-id)))
|
||||||
|
(message "[Noise] %s" name)))
|
||||||
|
|
||||||
(defun noise-receive--handle-sse-event (event)
|
(defun noise-receive--handle-sse-event (event)
|
||||||
"Handle an SSE EVENT from signal-cli.
|
"Handle an SSE EVENT from signal-cli.
|
||||||
Processes the envelope and updates UI."
|
Processes the envelope and updates UI."
|
||||||
(noise-db-init)
|
(noise-db-init)
|
||||||
(when-let ((envelope (noise-receive--field event "envelope")))
|
(when-let ((envelope (noise-receive--field event "envelope")))
|
||||||
(when-let ((conv-id (noise-receive--process-envelope envelope)))
|
(when-let ((conv-id (noise-receive--process-envelope envelope)))
|
||||||
(noise-conversation-refresh-for conv-id)
|
(let ((buf (noise-conversation--buffer-for conv-id)))
|
||||||
|
(if (and buf (get-buffer-window buf t))
|
||||||
|
(noise-conversation-refresh-for conv-id)
|
||||||
|
(noise-receive--announce-message conv-id)))
|
||||||
(when-let ((buf (get-buffer "*signal*")))
|
(when-let ((buf (get-buffer "*signal*")))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(noise-chat-list--render))))))
|
(noise-chat-list--render))))))
|
||||||
|
|||||||
@@ -76,11 +76,27 @@ Queries the daemon for registered accounts and sets `noise-account'."
|
|||||||
(noise-rpc-error
|
(noise-rpc-error
|
||||||
(message "Error: %s" (cdr err)))))
|
(message "Error: %s" (cdr err)))))
|
||||||
|
|
||||||
|
(defun noise--unread-lighter ()
|
||||||
|
"Return the mode-line lighter string with unread count."
|
||||||
|
(let ((count 0))
|
||||||
|
(when (and (boundp 'noise-db--connection)
|
||||||
|
noise-db--connection
|
||||||
|
(fboundp 'sqlitep)
|
||||||
|
(sqlitep noise-db--connection))
|
||||||
|
(condition-case nil
|
||||||
|
(setq count (or (caar (sqlite-select noise-db--connection
|
||||||
|
"SELECT COALESCE(SUM(unread_count), 0) FROM conversations"))
|
||||||
|
0))
|
||||||
|
(error 0)))
|
||||||
|
(if (> count 0)
|
||||||
|
(format " Noise[%d]" count)
|
||||||
|
" Noise")))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(define-minor-mode noise-mode
|
(define-minor-mode noise-mode
|
||||||
"Toggle Noise Signal client mode."
|
"Toggle Noise Signal client mode."
|
||||||
:global t
|
:global t
|
||||||
:lighter " Noise"
|
:lighter (:eval (noise--unread-lighter))
|
||||||
:group 'noise
|
:group 'noise
|
||||||
(if noise-mode
|
(if noise-mode
|
||||||
(progn
|
(progn
|
||||||
@@ -88,6 +104,5 @@ Queries the daemon for registered accounts and sets `noise-account'."
|
|||||||
(noise-receive-start-sse))
|
(noise-receive-start-sse))
|
||||||
(noise-receive-stop-sse)
|
(noise-receive-stop-sse)
|
||||||
(message "Noise mode disabled")))
|
(message "Noise mode disabled")))
|
||||||
|
|
||||||
(provide 'noise)
|
(provide 'noise)
|
||||||
;;; noise.el ends here
|
;;; noise.el ends here
|
||||||
|
|||||||
@@ -208,3 +208,28 @@
|
|||||||
(should (string-match-p "Sarah> from sse" (buffer-string))))
|
(should (string-match-p "Sarah> from sse" (buffer-string))))
|
||||||
(let ((msg (car (noise-db-get-messages "+1"))))
|
(let ((msg (car (noise-db-get-messages "+1"))))
|
||||||
(should (string= "from sse" (gethash "body" msg))))))
|
(should (string= "from sse" (gethash "body" msg))))))
|
||||||
|
|
||||||
|
(ert-deftest noise-receive-sse-stores-then-open-shows-message ()
|
||||||
|
"An SSE event stores the message; opening the conversation later shows it."
|
||||||
|
(noise-receive-test--with-db
|
||||||
|
;; No conversation buffer open — simulate SSE event arriving
|
||||||
|
(noise-receive--handle-sse-event
|
||||||
|
(noise-receive-test--ht
|
||||||
|
"envelope"
|
||||||
|
(noise-receive-test--ht
|
||||||
|
"sourceNumber" "+1" "sourceName" "Sarah"
|
||||||
|
"dataMessage" (noise-receive-test--ht
|
||||||
|
"timestamp" 1717930000000
|
||||||
|
"message" "hello from the void"))))
|
||||||
|
;; Verify message is in DB
|
||||||
|
(let ((msgs (noise-db-get-messages "+1")))
|
||||||
|
(should (= 1 (length msgs)))
|
||||||
|
(should (string= "hello from the void" (gethash "body" (car msgs)))))
|
||||||
|
;; Verify conversation has unread count
|
||||||
|
(let ((conv (noise-db-get-conversation "+1")))
|
||||||
|
(should (= 1 (gethash "unread_count" conv))))
|
||||||
|
;; Now open the conversation and verify message renders
|
||||||
|
(require 'noise-conversation)
|
||||||
|
(with-current-buffer (noise-conversation-open "+1")
|
||||||
|
(should (string-match-p "Sarah> hello from the void" (buffer-string)))
|
||||||
|
(should (= 0 (gethash "unread_count" (noise-db-get-conversation "+1")))))))
|
||||||
|
|||||||
Reference in New Issue
Block a user