diff --git a/noise-receive.el b/noise-receive.el index e278203..e14dce4 100644 --- a/noise-receive.el +++ b/noise-receive.el @@ -2,31 +2,22 @@ ;;; Commentary: -;; Fetches new envelopes from signal-cli via the receive JSON-RPC method +;; Fetches new envelopes from signal-cli via SSE or JSON-RPC ;; and stores them in the local database: incoming messages, messages ;; sent from other linked devices (sync), delivery/read receipts, and -;; typing indicators. `noise-receive-start-polling' polls on a timer. +;; typing indicators. `noise-receive-start-sse' connects to the SSE +;; endpoint for real-time message reception. ;;; Code: (require 'noise-rpc) (require 'noise-db) (require 'noise-conversation) +(require 'noise-sse) (require 'cl-lib) (declare-function noise-chat-list--render "noise-chat-list") -(defcustom noise-receive-interval 5 - "Seconds between automatic polls of signal-cli for new messages." - :type 'integer - :group 'noise) - -(defvar noise-receive--timer nil - "Active polling timer, or nil.") - -(defvar noise-receive--last-poll-error nil - "Last error message shown by the poller, to avoid repeating it.") - ;;;###autoload (defun noise-receive () "Fetch and store new envelopes from signal-cli. @@ -53,38 +44,31 @@ Returns the number of new messages stored." (message "Received %d new message%s" new (if (= new 1) "" "s"))) new)) +(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) + (when-let ((buf (get-buffer "*signal*"))) + (with-current-buffer buf + (noise-chat-list--render)))))) + +;; Override the default handler in noise-sse +(setq noise-sse--handle-event #'noise-receive--handle-sse-event) + ;;;###autoload -(defun noise-receive-start-polling () - "Start polling signal-cli for new messages every `noise-receive-interval'." +(defun noise-receive-start-sse () + "Start receiving messages via SSE." (interactive) - (noise-receive-stop-polling) - (setq noise-receive--timer - (run-with-timer 0 noise-receive-interval #'noise-receive--poll))) + (noise-sse-connect)) -(defun noise-receive-stop-polling () - "Stop the message polling timer." +;;;###autoload +(defun noise-receive-stop-sse () + "Stop receiving messages via SSE." (interactive) - (when noise-receive--timer - (cancel-timer noise-receive--timer) - (setq noise-receive--timer nil))) - -(defun noise-receive--poll () - "Poll for messages. -Errors are shown in the echo area once per distinct error rather than -on every poll, and never abort the timer." - (condition-case err - (progn - (noise-receive) - (setq noise-receive--last-poll-error nil)) - (error - (let ((text (error-message-string err))) - (unless (equal text noise-receive--last-poll-error) - (setq noise-receive--last-poll-error text) - (message "Noise: receiving failed: %s%s" - text - (if (string-match-p "account parameter" text) - " — set `noise-account' or run M-x noise-select-account" - ""))))))) + (noise-sse-disconnect)) ;;; Envelope processing diff --git a/test/noise-receive-poll-test.el b/test/noise-receive-poll-test.el deleted file mode 100644 index 40387c1..0000000 --- a/test/noise-receive-poll-test.el +++ /dev/null @@ -1,42 +0,0 @@ -;;; noise-receive-poll-test.el --- Tests for the receive poller -*- lexical-binding: t; -*- - -(require 'ert) -(require 'noise-receive) - -(ert-deftest noise-receive--poll-surfaces-error-once () - "A failing poll messages the user once, not on every retry." - (let ((noise-receive--last-poll-error nil) - (messages nil)) - (cl-letf (((symbol-function 'noise-receive) - (lambda () - (signal 'noise-rpc-error - '("signal-cli error -32602: Method requires valid account parameter")))) - ((symbol-function 'message) - (lambda (fmt &rest args) - (push (apply #'format fmt args) messages)))) - (noise-receive--poll) - (noise-receive--poll)) - (should (= 1 (length messages))) - (should (string-match-p "account parameter" (car messages))) - ;; the hint points at the fix - (should (string-match-p "noise-select-account" (car messages))))) - -(ert-deftest noise-receive--poll-recovers-and-resets () - "After a successful poll, a recurring error is shown again." - (let ((noise-receive--last-poll-error nil) - (messages nil) - (fail t)) - (cl-letf (((symbol-function 'noise-receive) - (lambda () - (when fail - (signal 'noise-rpc-error '("connection refused"))) - 0)) - ((symbol-function 'message) - (lambda (fmt &rest args) - (push (apply #'format fmt args) messages)))) - (noise-receive--poll) ; error -> message - (setq fail nil) - (noise-receive--poll) ; success -> resets - (setq fail t) - (noise-receive--poll)) ; error again -> message again - (should (= 2 (length messages)))))