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

    muc: Separate room state
---
 lisp/jabber-alert.el               |  3 +-
 lisp/jabber-bookmarks.el           |  3 +-
 lisp/jabber-chat.el                |  3 +-
 lisp/jabber-chatstates.el          |  2 +-
 lisp/jabber-db.el                  |  2 +-
 lisp/jabber-httpupload.el          |  2 +-
 lisp/jabber-mam.el                 |  2 +-
 lisp/jabber-muc-nick-completion.el |  2 +-
 lisp/jabber-muc-state.el           | 86 ++++++++++++++++++++++++++++++++++++++
 lisp/jabber-muc.el                 | 74 +-------------------------------
 lisp/jabber-omemo.el               |  2 +-
 lisp/jabber-presence.el            |  7 +---
 lisp/jabber-reactions.el           |  2 +-
 lisp/jabber-roster.el              |  3 +-
 lisp/jabber-util.el                |  1 -
 15 files changed, 100 insertions(+), 94 deletions(-)

diff --git a/lisp/jabber-alert.el b/lisp/jabber-alert.el
index 4e3f318a84..b61d9fdbb6 100644
--- a/lisp/jabber-alert.el
+++ b/lisp/jabber-alert.el
@@ -30,6 +30,7 @@
 (require 'cl-lib)
 (require 'jabber-util)
 (require 'jabber-xml)
+(require 'jabber-muc-state)
 
 (defgroup jabber-alerts nil
   "Auditory and visual alerts for Jabber events."
@@ -242,8 +243,6 @@ files."
 (declare-function jabber-chat-send "jabber-chat.el"
                   (jc body &optional extra-elements))
 (declare-function jabber-muc-sender-p "jabber-muc.el" (jid))
-(declare-function jabber-muc-nickname "jabber-muc.el" (group &optional jc))
-(declare-function jabber-muc-our-nick-p "jabber-muc.el" (group nick))
 (defvar jabber-presence-strings)        ; jabber.el
 (defvar jabber-xml-data)                ; jabber.el
 (defvar jabber-buffer-connection)       ; jabber-chatbuffer.el
diff --git a/lisp/jabber-bookmarks.el b/lisp/jabber-bookmarks.el
index c2ff67e3cb..bb44f5a2c0 100644
--- a/lisp/jabber-bookmarks.el
+++ b/lisp/jabber-bookmarks.el
@@ -31,6 +31,7 @@
 
 (require 'jabber-private)
 (require 'jabber-pubsub)
+(require 'jabber-muc-state)
 (require 'keymap-popup)
 
 (defconst jabber-bookmarks-xmlns "storage:bookmarks"
@@ -59,8 +60,6 @@
 
 (declare-function jabber-disco-get-info "jabber-disco.el"
                   (jc jid node callback closure-data &optional force))
-(declare-function jabber-muc-joined-p "jabber-muc" (group &optional jc))
-(declare-function jabber-muc-nickname "jabber-muc" (group &optional jc))
 (declare-function jabber-muc-join "jabber-muc" (jc group nickname &optional 
popup))
 (declare-function jabber-muc-leave "jabber-muc" (jc group))
 (declare-function jabber-muc-get-buffer "jabber-muc" (group &optional jc))
diff --git a/lisp/jabber-chat.el b/lisp/jabber-chat.el
index c26ebf54f7..ae12b60a5f 100644
--- a/lisp/jabber-chat.el
+++ b/lisp/jabber-chat.el
@@ -39,6 +39,7 @@
 (require 'url-queue)
 (require 'hex-util)
 (require 'jabber-image)
+(require 'jabber-muc-state)
 ;; For the `image-property' setf-expander (not preloaded on emacs-nox).
 (require 'image)
 
@@ -273,8 +274,6 @@ holding state for the next composed message stay inert."
 (declare-function jabber-muc-message-p "jabber-muc.el"(message))
 (declare-function jabber-muc-sender-p "jabber-muc.el" (jid))
 (declare-function jabber-muc-private-message-p "jabber-muc.el" (message))
-(declare-function jabber-muc-nickname "jabber-muc.el" (group &optional jc))
-(declare-function jabber-muc-our-nick-p "jabber-muc.el" (group nick))
 (defvar jabber-muc-xmlns-user)
 (declare-function jabber-omemo-aesgcm-decrypt "jabber-omemo"
                   (key iv ciphertext-with-tag))
diff --git a/lisp/jabber-chatstates.el b/lisp/jabber-chatstates.el
index 33e2b4a5ff..68b9d3c119 100644
--- a/lisp/jabber-chatstates.el
+++ b/lisp/jabber-chatstates.el
@@ -36,6 +36,7 @@
 (require 'jabber-chat)
 (require 'jabber-chatbuffer)
 (require 'jabber-disco)
+(require 'jabber-muc-state)
 (require 'jabber-xml)
 
 
@@ -43,7 +44,6 @@
 (defvar jabber-chatting-with)           ; jabber-chat.el
 
 (declare-function jabber-muc-find-buffer "jabber-muc" (group))
-(declare-function jabber-muc-nickname "jabber-muc" (group &optional jc))
 (declare-function jabber-reactions--reaction-only-p "jabber-reactions" 
(xml-data))
 
 (defgroup jabber-chatstates nil
diff --git a/lisp/jabber-db.el b/lisp/jabber-db.el
index 79b71436f7..696c0e6ec9 100644
--- a/lisp/jabber-db.el
+++ b/lisp/jabber-db.el
@@ -38,11 +38,11 @@
 (require 'subr-x)
 (require 'jabber-util)
 (require 'jabber-xml)
+(require 'jabber-muc-state)
 (eval-when-compile
   (require 'cl-lib)
   (require 'seq))
 
-(declare-function jabber-muc-joined-p "jabber-muc" (group &optional jc))
 (declare-function jabber-muc-sender-p "jabber-muc" (jid))
 (defvar jabber-chatting-with)           ; jabber-chat.el
 (defvar jabber-chat-send-hooks)        ; jabber-chat.el
diff --git a/lisp/jabber-httpupload.el b/lisp/jabber-httpupload.el
index 63e996c3ea..b3f9b481d2 100644
--- a/lisp/jabber-httpupload.el
+++ b/lisp/jabber-httpupload.el
@@ -43,11 +43,11 @@
 (require 'mailcap)
 (require 'subr-x)
 (require 'jabber)
+(require 'jabber-muc-state)
 
 (declare-function jabber-chat-send "jabber-chat.el"
                   (jc body &optional extra-elements))
 (declare-function jabber-chat-create-buffer "jabber-chat.el" (jc chat-with))
-(declare-function jabber-muc-joined-p "jabber-muc.el" (group &optional jc))
 (defvar jabber-oob-xmlns)              ; jabber-xml.el
 
 (defconst jabber-httpupload-xmlns "urn:xmpp:http:upload:0"
diff --git a/lisp/jabber-mam.el b/lisp/jabber-mam.el
index 84f89a4815..10e2f68bd3 100644
--- a/lisp/jabber-mam.el
+++ b/lisp/jabber-mam.el
@@ -39,6 +39,7 @@
 (require 'jabber-disco)
 (require 'jabber-iq)
 (require 'jabber-message-correct)
+(require 'jabber-muc-state)
 
 (eval-when-compile (require 'cl-lib))
 
@@ -388,7 +389,6 @@ comparing with the account username to handle nick changes."
         (string= nick my-nick))
       (string= nick (plist-get (fsm-get-state-data jc) :username))))
 
-(declare-function jabber-muc-nickname "jabber-muc" (group &optional jc))
 
 (defun jabber-mam--mark-dirty (peer type)
   "Record that PEER's buffer needs redisplay after sync.
diff --git a/lisp/jabber-muc-nick-completion.el 
b/lisp/jabber-muc-nick-completion.el
index cab0d0ebeb..ba51ff21af 100644
--- a/lisp/jabber-muc-nick-completion.el
+++ b/lisp/jabber-muc-nick-completion.el
@@ -34,6 +34,7 @@
 (require 'cl-lib)
 
 (require 'jabber-chatbuffer)
+(require 'jabber-muc-state)
 
 ;;; User customizations here:
 (defcustom jabber-muc-completion-delimiter ": "
@@ -65,7 +66,6 @@ Note that \":\" or alike not needed (it appended in other 
string)"
 
 ;; Global reference declarations
 
-(declare-function jabber-muc-nickname "jabber-muc.el" (group &optional jc))
 (defvar jabber-group)                   ; jabber-muc.el
 (defvar jabber-muc-default-nicknames)   ; jabber-muc.el
 (defvar jabber-muc-participants)        ; jabber-muc.el
diff --git a/lisp/jabber-muc-state.el b/lisp/jabber-muc-state.el
new file mode 100644
index 0000000000..5de039f2b5
--- /dev/null
+++ b/lisp/jabber-muc-state.el
@@ -0,0 +1,86 @@
+;;; jabber-muc-state.el --- Multi-user chat state  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2026  Thanos Apollo
+
+;; Maintainer: Thanos Apollo <[email protected]>
+
+;; This file is a part of jabber.el.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2 of the License, or
+;; (at your option) any later version.
+
+;;; Commentary:
+
+;; Track joined rooms independently from MUC protocol handling and buffers.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'subr-x)
+
+(defvar jabber-muc--rooms (make-hash-table :test #'equal)
+  "Map room JIDs to lists of connection and nickname pairs.")
+
+(defvar jabber-muc--generation 0
+  "Generation counter incremented after every room-state change.")
+
+(defun jabber-muc-nickname (group &optional jc)
+  "Return our nickname in GROUP, optionally restricted to JC."
+  (let ((entries (gethash group jabber-muc--rooms)))
+    (if jc
+        (alist-get jc entries)
+      (cdar entries))))
+
+(defun jabber-muc-connection (group)
+  "Return the first connection joined to GROUP, or nil."
+  (caar (gethash group jabber-muc--rooms)))
+
+(defun jabber-muc-joined-p (group &optional jc)
+  "Return non-nil when GROUP is joined, optionally through JC."
+  (let ((entries (gethash group jabber-muc--rooms)))
+    (if jc
+        (and (assq jc entries) t)
+      (and entries t))))
+
+(defun jabber-muc-our-nick-p (group nick)
+  "Return non-nil when NICK belongs to us in GROUP."
+  (cl-some (lambda (entry) (string= nick (cdr entry)))
+           (gethash group jabber-muc--rooms)))
+
+(defun jabber-muc-room-entries (group)
+  "Return connection and nickname pairs for GROUP."
+  (gethash group jabber-muc--rooms))
+
+(defun jabber-muc-active-rooms ()
+  "Return the JIDs of all joined rooms."
+  (hash-table-keys jabber-muc--rooms))
+
+(defun jabber-muc-join-set (group jc nickname)
+  "Record that JC joined GROUP as NICKNAME."
+  (let ((entries (gethash group jabber-muc--rooms)))
+    (if-let* ((existing (assq jc entries)))
+        (setcdr existing nickname)
+      (push (cons jc nickname) entries))
+    (puthash group entries jabber-muc--rooms))
+  (cl-incf jabber-muc--generation))
+
+(defun jabber-muc-leave-remove (group &optional jc)
+  "Remove GROUP state, or only the entry associated with JC."
+  (if jc
+      (let ((entries (assq-delete-all
+                      jc (gethash group jabber-muc--rooms))))
+        (if entries
+            (puthash group entries jabber-muc--rooms)
+          (remhash group jabber-muc--rooms)))
+    (remhash group jabber-muc--rooms))
+  (cl-incf jabber-muc--generation))
+
+(defun jabber-muc-generation ()
+  "Return the room-state generation counter."
+  jabber-muc--generation)
+
+(provide 'jabber-muc-state)
+
+;;; jabber-muc-state.el ends here
diff --git a/lisp/jabber-muc.el b/lisp/jabber-muc.el
index bdc7417dc4..1186159784 100644
--- a/lisp/jabber-muc.el
+++ b/lisp/jabber-muc.el
@@ -33,6 +33,7 @@
 (require 'ewoc)
 (require 'jabber-widget)
 (require 'jabber-disco)
+(require 'jabber-muc-state)
 (require 'jabber-bookmarks)
 (require 'jabber-chat)
 (require 'jabber-db)
@@ -53,79 +54,6 @@
 (defconst jabber-muc-xmlns-direct-invite "jabber:x:conference"
   "XEP-0249 Direct MUC Invitations namespace.")
 
-(defvar jabber-muc--rooms (make-hash-table :test #'equal)
-  "Internal hash table of active MUC rooms.
-Keys are group JID strings; values are lists of (JC . NICKNAME)
-cons cells, one per connection that has joined the room.  This
-allows multiple accounts to be in the same room simultaneously.")
-
-(defvar jabber-muc--generation 0
-  "Generation counter for `jabber-muc--rooms'.
-Incremented on every join/leave, enabling cheap change detection
-without copying the room list.")
-
-(defun jabber-muc-nickname (group &optional jc)
-  "Return our nickname in GROUP, or nil.
-If JC is given, return the nickname for that specific connection.
-Otherwise return the nickname from the first entry."
-  (let ((entries (gethash group jabber-muc--rooms)))
-    (if jc
-        (alist-get jc entries)
-      (cdar entries))))
-
-(defun jabber-muc-connection (group)
-  "Return a connection object for GROUP, or nil.
-When multiple accounts are in the same room, returns the first."
-  (caar (gethash group jabber-muc--rooms)))
-
-(defun jabber-muc-joined-p (group &optional jc)
-  "Return non-nil if we are in GROUP.
-If JC is given, check whether that specific connection is in GROUP."
-  (let ((entries (gethash group jabber-muc--rooms)))
-    (if jc
-        (and (assq jc entries) t)
-      (and entries t))))
-
-(defun jabber-muc-our-nick-p (group nick)
-  "Return non-nil if NICK is our nickname in GROUP on any connection."
-  (let ((entries (gethash group jabber-muc--rooms)))
-    (cl-some (lambda (entry) (string= nick (cdr entry))) entries)))
-
-(defun jabber-muc-room-entries (group)
-  "Return list of (JC . NICKNAME) entries for GROUP."
-  (gethash group jabber-muc--rooms))
-
-(defun jabber-muc-active-rooms ()
-  "Return list of joined room JIDs."
-  (hash-table-keys jabber-muc--rooms))
-
-(defun jabber-muc-join-set (group jc nickname)
-  "Record that we joined GROUP via JC with NICKNAME."
-  (let ((entries (gethash group jabber-muc--rooms)))
-    (if-let* ((existing (assq jc entries)))
-        (setcdr existing nickname)
-      (push (cons jc nickname) entries))
-    (puthash group entries jabber-muc--rooms))
-  (cl-incf jabber-muc--generation))
-
-(defun jabber-muc-leave-remove (group &optional jc)
-  "Remove GROUP from active rooms.
-If JC is given, only remove that connection's entry; the room
-stays tracked if other connections remain in it."
-  (if jc
-      (let ((entries (gethash group jabber-muc--rooms)))
-        (setq entries (assq-delete-all jc entries))
-        (if entries
-            (puthash group entries jabber-muc--rooms)
-          (remhash group jabber-muc--rooms)))
-    (remhash group jabber-muc--rooms))
-  (cl-incf jabber-muc--generation))
-
-(defun jabber-muc-generation ()
-  "Return current generation counter for change detection."
-  jabber-muc--generation)
-
-
 (defvar jabber-pending-groupchats (make-hash-table)
   "Hash table of groupchats and nicknames.
 Keys are JID symbols; values are strings.
diff --git a/lisp/jabber-omemo.el b/lisp/jabber-omemo.el
index 52f3c243ae..e743175adc 100644
--- a/lisp/jabber-omemo.el
+++ b/lisp/jabber-omemo.el
@@ -40,12 +40,12 @@
 (require 'jabber-eme)
 (require 'jabber-chat)
 (require 'jabber-db)
+(require 'jabber-muc-state)
 
 (declare-function jabber-muc-modify-participant "jabber-muc"
                   (group nickname new-plist))
 (declare-function jabber-muc-participant-plist "jabber-muc"
                   (group nickname))
-(declare-function jabber-muc-joined-p "jabber-muc" (group &optional jc))
 (declare-function jabber-muc-create-buffer "jabber-muc" (jc group))
 (declare-function jabber-disco-advertise-feature "jabber-disco")
 (declare-function jabber-send-iq "jabber-iq")
diff --git a/lisp/jabber-presence.el b/lisp/jabber-presence.el
index cd1f5f4236..981cf29550 100644
--- a/lisp/jabber-presence.el
+++ b/lisp/jabber-presence.el
@@ -31,6 +31,7 @@
 (require 'jabber-iq)
 (require 'jabber-alert)
 (require 'jabber-util)
+(require 'jabber-muc-state)
 (require 'ewoc)
 
 (defconst jabber-presence-show-alist
@@ -64,10 +65,6 @@ stanza.")
 (declare-function jabber-muc-get-buffer "jabber-muc.el" (group &optional jc))
 (declare-function jabber-muc-process-presence "jabber-muc.el" (jc presence))
 (declare-function jabber-muc-presence-p "jabber-muc.el" (presence))
-(declare-function jabber-muc-active-rooms "jabber-muc.el" ())
-(declare-function jabber-muc-connection "jabber-muc.el" (group))
-(declare-function jabber-muc-nickname "jabber-muc.el" (group &optional jc))
-(declare-function jabber-muc-room-entries "jabber-muc.el" (group))
 (defvar jabber-chatting-with)           ; jabber-chat.el
 (defvar jabber-buffer-connection)       ; jabber-chatbuffer.el
 (defvar jabber-chat-ewoc)               ; jabber-chatbuffer.el
@@ -634,4 +631,4 @@ JC is the Jabber connection."
 
 (provide 'jabber-presence)
 
-;;; jabber-presence.el ends here
\ No newline at end of file
+;;; jabber-presence.el ends here
diff --git a/lisp/jabber-reactions.el b/lisp/jabber-reactions.el
index 846b936946..8f9a7b3e01 100644
--- a/lisp/jabber-reactions.el
+++ b/lisp/jabber-reactions.el
@@ -32,6 +32,7 @@
 (require 'jabber-db)
 (require 'jabber-disco)
 (require 'jabber-util)
+(require 'jabber-muc-state)
 
 (defconst jabber-reactions-xmlns "urn:xmpp:reactions:0"
   "XEP-0444 Message Reactions namespace.")
@@ -71,7 +72,6 @@ are not filtered against it."
 (declare-function jabber-chat-ewoc-invalidate "jabber-chatbuffer" (node))
 (declare-function jabber-chat-find-buffer "jabber-chat" (chat-with))
 (declare-function jabber-muc-find-buffer "jabber-muc" (group))
-(declare-function jabber-muc-nickname "jabber-muc" (group &optional jc))
 
 ;;; Pure helpers
 
diff --git a/lisp/jabber-roster.el b/lisp/jabber-roster.el
index 7455d4511d..e586e1feb2 100644
--- a/lisp/jabber-roster.el
+++ b/lisp/jabber-roster.el
@@ -34,6 +34,7 @@
 (require 'jabber-private)
 (require 'jabber-presence)
 (require 'jabber-carbons)
+(require 'jabber-muc-state)
 (require 'keymap-popup)
 
 (defgroup jabber-roster nil "Roster options."
@@ -115,8 +116,6 @@ Trailing newlines are always removed, regardless of this 
variable."
 (declare-function jabber-get-conference-data "jabber-bookmarks.el"
                   (jc conference-jid cont &optional key))
 (declare-function jabber-get-version "jabber-version.el" (jc to))
-(declare-function jabber-muc-active-rooms "jabber-muc.el" ())
-(declare-function jabber-muc-connection "jabber-muc.el" (group))
 (declare-function jabber-muc-join "jabber-muc.el"
                   (jc group nickname &optional popup))
 (declare-function jabber-muc-switch-to "jabber-muc.el" (group))
diff --git a/lisp/jabber-util.el b/lisp/jabber-util.el
index 78d6eb4929..08eae7fb4b 100644
--- a/lisp/jabber-util.el
+++ b/lisp/jabber-util.el
@@ -301,7 +301,6 @@ Candidates display sorted by availability, then name."
        (t
         (complete-with-action action table string pred))))))
 
-(declare-function jabber-muc-joined-p "jabber-muc.el" (group &optional jc))
 (defun jabber-read-jid-completing (prompt &optional subset require-match 
default resource fulljids)
   "Read a JID out of the current roster from the minibuffer, with PROMPT.
 If SUBSET is non-nil, it should be a list of symbols from which

Reply via email to