branch: elpa/jabber
commit d033c3e065de38aa99146cbcb1fff19cc4d36bd7
Author: Thanos Apollo <[email protected]>
Commit: Thanos Apollo <[email protected]>

    disco: Invert presence refresh dependency
---
 lisp/jabber-disco.el          | 18 +++++-------------
 lisp/jabber-presence.el       |  8 ++++++++
 tests/jabber-test-disco.el    | 16 ++++++++++++++++
 tests/jabber-test-presence.el |  9 +++++++++
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/lisp/jabber-disco.el b/lisp/jabber-disco.el
index 799ec5de8d..62839a1fc4 100644
--- a/lisp/jabber-disco.el
+++ b/lisp/jabber-disco.el
@@ -29,16 +29,11 @@
 ;;; Code:
 
 (require 'cl-lib)
+(require 'jabber-db)
 (require 'jabber-iq)
 (require 'jabber-xml)
 (require 'jabber-xdata)
 
-;; Global reference declarations
-
-(declare-function jabber-db-caps-store "jabber-db.el"
-                  (hash ver identities features))
-(declare-function jabber-db-caps-lookup "jabber-db.el" (hash ver))
-
 (defvar jabber-xdata-xmlns)            ; jabber-xml.el
 
 (defconst jabber-disco-xmlns-info "http://jabber.org/protocol/disco#info";
@@ -128,12 +123,11 @@ Second item is access control function.  That function is 
passed the
 JID, and returns non-nil if access is granted.  If the second item is
 nil, access is always granted.")
 
-;; Global reference declarations
-
-(declare-function jabber-send-current-presence "jabber-presence.el"
-                  (&optional jc))
 (defvar jabber-presence-element-functions nil) ; jabber-presence.el
 
+(defvar jabber-disco-features-changed-hook nil
+  "Hook run after connected clients advertise a new feature.")
+
 ;;
 
 (add-to-list 'jabber-iq-get-xmlns-alist
@@ -414,9 +408,7 @@ The value should be a key in `jabber-caps-hash-names'.")
     (push feature jabber-advertised-features)
     (when jabber-caps-current-hash
       (jabber-caps-recalculate-hash)
-      ;; If we're already connected, we need to send updated presence
-      ;; for the new feature.
-      (mapc #'jabber-send-current-presence jabber-connections))))
+      (run-hooks 'jabber-disco-features-changed-hook))))
 
 (defun jabber-caps-recalculate-hash ()
   "Update `jabber-caps-current-hash' for feature list change.
diff --git a/lisp/jabber-presence.el b/lisp/jabber-presence.el
index cc43a971da..58a3ed71ee 100644
--- a/lisp/jabber-presence.el
+++ b/lisp/jabber-presence.el
@@ -28,6 +28,7 @@
 ;;; Code:
 
 (require 'jabber-core)
+(require 'jabber-disco)
 (require 'jabber-iq)
 (require 'jabber-alert)
 (require 'jabber-util)
@@ -556,6 +557,13 @@ If JC is non-nil, send only for that connection."
                            jabber-current-priority jc)
     (jabber-send-default-presence jc)))
 
+(defun jabber-presence--refresh-advertised-features ()
+  "Resend presence with the current advertised feature set."
+  (mapc #'jabber-send-current-presence jabber-connections))
+
+(add-hook 'jabber-disco-features-changed-hook
+          #'jabber-presence--refresh-advertised-features)
+
 (defun jabber-send-subscription-request (jc to &optional request)
   "Send a subscription request to TO.
 REQUEST, if non-empty, is included as the status text.
diff --git a/tests/jabber-test-disco.el b/tests/jabber-test-disco.el
index bcd379ba3a..157040994a 100644
--- a/tests/jabber-test-disco.el
+++ b/tests/jabber-test-disco.el
@@ -177,5 +177,21 @@
       ;; Query should have been sent.
       (should iq-sent))))
 
+(ert-deftest jabber-test-disco-advertise-feature-runs-change-hook-once ()
+  "Advertising a new connected feature runs the change hook once."
+  (let ((jabber-advertised-features nil)
+        (jabber-caps-current-hash "old")
+        (jabber-disco-features-changed-hook nil)
+        (recalculations 0)
+        (changes 0))
+    (add-hook 'jabber-disco-features-changed-hook
+              (lambda () (cl-incf changes)))
+    (cl-letf (((symbol-function 'jabber-caps-recalculate-hash)
+               (lambda () (cl-incf recalculations))))
+      (jabber-disco-advertise-feature "urn:test:feature")
+      (jabber-disco-advertise-feature "urn:test:feature"))
+    (should (= recalculations 1))
+    (should (= changes 1))))
+
 (provide 'jabber-test-disco)
 ;;; jabber-test-disco.el ends here
diff --git a/tests/jabber-test-presence.el b/tests/jabber-test-presence.el
index 8b76dad89f..bfe3c234cc 100644
--- a/tests/jabber-test-presence.el
+++ b/tests/jabber-test-presence.el
@@ -46,6 +46,15 @@
     (should (equal (jabber-presence-children nil)
                    '((c ((xmlns . "urn:xmpp:caps"))))))))
 
+(ert-deftest jabber-test-presence-refreshes-features-on-all-connections ()
+  "A discovery feature change resends presence on every connection."
+  (let ((jabber-connections '(first second))
+        (sent nil))
+    (cl-letf (((symbol-function 'jabber-send-current-presence)
+               (lambda (jc) (push jc sent))))
+      (jabber-presence--refresh-advertised-features))
+    (should (equal (nreverse sent) jabber-connections))))
+
 ;;; Group 2: jabber--roster-valid-push-p
 
 (ert-deftest jabber-test-presence-valid-push-nil-from ()

Reply via email to