emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ement 24320f23af 1/5: Fix sender header insertion with


From: ELPA Syncer
Subject: [elpa] externals/ement 24320f23af 1/5: Fix sender header insertion with respect to membership changes
Date: Sun, 14 Jan 2024 07:11:05 -0500 (EST)

branch: externals/ement
commit 24320f23af15c59a53327eda8ea5b1de974b716f
Author: Steven Allen <steven@stebalien.com>
Commit: Adam Porter <adam@alphapapa.net>

    Fix sender header insertion with respect to membership changes
    
    Only insert a sender header if the previous message is from a different
    sender, and there is no sender header between the current message and
    the previous message.
    
    While the previous version of this function explicitly skipped the read
    marker, this version searches for known events (messages and sender
    headers), skipping everything it doesn't understand. This should make it
    robust to adding new events, widgets, etc.
    
    fixes #157
    
    Fix new event insertion with respect to sender headers
    
    Only skip over the read marker, don't skip over sender headers.
    
    Make sender headers robust
    
    1. Widen the "fixup" range to the next message after the end-node.
    2. Simplify the loop logic.
    3. Fixup incorrect sender headers.
---
 ement-room.el | 97 ++++++++++++++++++++++++-----------------------------------
 1 file changed, 40 insertions(+), 57 deletions(-)

diff --git a/ement-room.el b/ement-room.el
index ff4ecd73ea..dde1baf556 100644
--- a/ement-room.el
+++ b/ement-room.el
@@ -3014,63 +3014,43 @@ the first and last nodes in the buffer, respectively."
   "Insert sender headers into EWOC.
 Inserts headers between START-NODE and END-NODE, which default to
 the first and last nodes in the buffer, respectively."
-  (cl-labels ((read-marker-p (data)
-                (member data '(ement-room-fully-read-marker
-                               ement-room-read-receipt-marker)))
-              (message-event-p (data)
-                (and (ement-event-p data)
-                     (equal "m.room.message" (ement-event-type data))))
-              (insert-sender-before (node)
-                (ewoc-enter-before ewoc node (ement-event-sender (ewoc-data 
node)))))
-    (let* ((event-node (if (ement-event-p (ewoc-data start-node))
-                           start-node
-                         (ement-room--ewoc-next-matching ewoc start-node
-                           #'ement-event-p)))
-           (prev-node (when event-node
-                        ;; Just in case...
-                        (ewoc-prev ewoc event-node))))
-      (while (and event-node
-                  ;; I don't like looking up the location of these nodes on 
every loop
-                  ;; iteration, but it seems like the only reliable way to 
determine
-                  ;; whether we've reached the end node.  However, when this 
function is
-                  ;; called for short batches of events (or even a single 
event, like when
-                  ;; called from `ement-room--insert-event'), the overhead 
should be
-                  ;; minimal.
-                  (<= (ewoc-location event-node) (ewoc-location end-node)))
-        (when (message-event-p (ewoc-data event-node))
-          (if (not prev-node)
-              ;; No previous node and event is a message: insert header.
-              (insert-sender-before event-node)
-            ;; Previous node exists.
-            (when (read-marker-p (ewoc-data prev-node))
-              ;; Previous node is a read marker: we want to act as if they 
don't exist, so
-              ;; we set `prev-node' to the non-marker node before it.
-              (setf prev-node (ement-room--ewoc-next-matching ewoc prev-node
-                                (lambda (data)
-                                  (not (read-marker-p data)))
-                                #'ewoc-prev)))
-            (when prev-node
-              ;; A previous node still exists: maybe we need to add a header.
-              (cl-typecase (ewoc-data prev-node)
-                (ement-event
-                 ;; Previous node is an event.
-                 (when (and (message-event-p (ewoc-data prev-node))
-                            (not (equal (ement-event-sender (ewoc-data 
prev-node))
-                                        (ement-event-sender (ewoc-data 
event-node)))))
-                   ;; Previous node is a message event with a different 
sender: insert
-                   ;; header.
-                   (insert-sender-before event-node)))
-                ((or ement-user ement-room-membership-events)
-                 ;; Previous node is a user or coalesced membership events: do 
not insert
-                 ;; header.
-                 nil)
-                (t
-                 ;; Previous node is not an event and not a read marker: 
insert header.
-                 (insert-sender-before event-node))))))
+  (cl-labels ((message-event-p
+                (data) (and (ement-event-p data)
+                            (equal "m.room.message" (ement-event-type data)))))
+    ;; If we're not starting at a message node, forward to the previous 
message.
+    ;; If we don't find any messages, there's nothing to do anyways.
+    (when (and start-node (not (message-event-p (ewoc-data start-node))))
+      (setf start-node (ement-room--ewoc-next-matching ewoc start-node 
#'message-event-p)))
+
+    ;; Set the end node to the next message after the end node, if any. This:
+    ;; 1. Makes the loop check simple (we continue going until we run out of 
nodes or our
+    ;;    we find the end node).
+    ;; 2. Ensures we fix up sender headers after any inserted messages.
+    (when end-node
+      (setf end-node (ement-room--ewoc-next-matching ewoc end-node 
#'message-event-p)))
+
+    (let* ((event-node start-node) prev-node)
+      (while (and event-node (not (eq event-node end-node)))
+        ;; Scan back for the previous message or user header, if any.
+        (setf prev-node (ement-room--ewoc-next-matching ewoc event-node
+                          (lambda (data)
+                            (or (ement-user-p data) (message-event-p data)))
+                          #'ewoc-prev))
+
+        (let ((sender (ement-event-sender (ewoc-data event-node))))
+          (cond
+           ;; No previous message/sender, insert a sender.
+           ((not prev-node) (ewoc-enter-before ewoc event-node sender))
+           ;; We have a previous sender, but it's wrong. Fix it.
+           ((ement-user-p (ewoc-data prev-node))
+            (unless (equal sender (ewoc-data prev-node))
+              (ewoc-set-data prev-node sender)))
+           ;; Otherwise, it's a message. Insert a sender if it's from a 
different user.
+           ((not (equal sender (ement-event-sender (ewoc-data prev-node))))
+            (ewoc-enter-before ewoc event-node sender))))
+
         (setf event-node (ement-room--ewoc-next-matching ewoc event-node
-                           #'ement-event-p)
-              prev-node (when event-node
-                          (ewoc-prev ewoc event-node)))))))
+                           #'message-event-p))))))
 
 (defun ement-room--coalesce-nodes (a b ewoc)
   "Try to coalesce events in nodes A and B in EWOC.
@@ -3118,6 +3098,9 @@ Search starts from node START and moves by NEXT."
                   ((pred ement-event-p) t)
                   ((pred ement-room-membership-events-p) t)
                   (`(ts . ,_) t)))
+              (read-marker-p
+                (data) (member data '(ement-room-fully-read-marker
+                                      ement-room-read-receipt-marker)))
               (node-ts (data)
                 (pcase data
                   ((pred ement-event-p) (ement-event-origin-server-ts data))
@@ -3137,7 +3120,7 @@ Search starts from node START and moves by NEXT."
       ;; HACK: Insert after any read markers.
       (cl-loop for node-after-node-before = (ewoc-next ewoc event-node-before)
                while node-after-node-before
-               while (not (ement-event-p (ewoc-data node-after-node-before)))
+               while (read-marker-p (ewoc-data node-after-node-before))
                do (setf event-node-before node-after-node-before))
       (setf new-node (if (not event-node-before)
                          (progn



reply via email to

[Prev in Thread] Current Thread [Next in Thread]