diff --git a/noise-conversation.el b/noise-conversation.el index 95ab8f3..f807c6a 100644 --- a/noise-conversation.el +++ b/noise-conversation.el @@ -245,5 +245,19 @@ NAME is the contact typing; ACTION is signal-cli's STARTED or STOPPED." (with-current-buffer buf (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) ;;; noise-conversation.el ends here diff --git a/noise-receive.el b/noise-receive.el index fb0d00d..ab17e46 100644 --- a/noise-receive.el +++ b/noise-receive.el @@ -44,13 +44,22 @@ Returns the number of new messages stored." (message "Received %d new message%s" new (if (= new 1) "" "s"))) 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) "Handle an SSE EVENT from signal-cli. Processes the envelope and updates UI." (noise-db-init) (when-let ((envelope (noise-receive--field event "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*"))) (with-current-buffer buf (noise-chat-list--render)))))) diff --git a/noise.el b/noise.el index a998c94..2558bda 100644 --- a/noise.el +++ b/noise.el @@ -76,11 +76,27 @@ Queries the daemon for registered accounts and sets `noise-account'." (noise-rpc-error (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 (define-minor-mode noise-mode "Toggle Noise Signal client mode." :global t - :lighter " Noise" + :lighter (:eval (noise--unread-lighter)) :group 'noise (if noise-mode (progn @@ -88,6 +104,5 @@ Queries the daemon for registered accounts and sets `noise-account'." (noise-receive-start-sse)) (noise-receive-stop-sse) (message "Noise mode disabled"))) - (provide 'noise) ;;; noise.el ends here diff --git a/test/noise-receive-test.el b/test/noise-receive-test.el index bf1bbcb..ac7a997 100644 --- a/test/noise-receive-test.el +++ b/test/noise-receive-test.el @@ -208,3 +208,28 @@ (should (string-match-p "Sarah> from sse" (buffer-string)))) (let ((msg (car (noise-db-get-messages "+1")))) (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")))))))