@@ -1101,7 +1101,7 @@ option."
11011101 right-margin-width ement-room-right-margin-width)
11021102 (set-window-margins nil left-margin-width right-margin-width)
11031103 (if ement-room-sender-in-headers
1104- (ement-room--insert-sender-headers)
1104+ (ement-room--insert-sender-headers ement-ewoc )
11051105 (ewoc-filter ement-ewoc (lambda (node-data )
11061106 ; ; Return non-nil for nodes that should stay.
11071107 (not (ement-user-p node-data)))))
@@ -1887,6 +1887,8 @@ the previously oldest event."
18871887 ; ; for a long time, as the time to do this in each buffer will increase with the
18881888 ; ; number of events. At least we only do it once per batch of events.)
18891889 (ement-room--insert-ts-headers nil (when retro orig-first-node))
1890+ (when ement-room-sender-in-headers
1891+ (ement-room--insert-sender-headers ement-ewoc))
18901892 (when buffer-window
18911893 (cond (retro (with-selected-window buffer-window
18921894 (set-window-start buffer-window (ewoc-location point-node))
@@ -2023,6 +2025,7 @@ data slot."
20232025 (ement-room--process-events (reverse (ement-room-state room)))
20242026 (ement-room--process-events (reverse (ement-room-timeline room)))
20252027 (ement-room--insert-ts-headers)
2028+ (ement-room--insert-sender-headers ement-ewoc)
20262029 (ement-room-move-read-markers room
20272030 :read-event (when-let ((event (alist-get " m.read" (ement-room-account-data room) nil nil #'equal )))
20282031 (map-nested-elt event '(content event_id)))
@@ -2669,55 +2672,71 @@ the first and last nodes in the buffer, respectively."
26692672 ; ; cause it to be marked modified, like moving the read markers).
26702673 (ewoc-enter-after ewoc node-a (list 'ts b-ts))))))))
26712674
2672- (defun ement-room--insert-sender-headers (&optional start-node end-node )
2675+ (cl-defun ement-room--insert-sender-headers
2676+ (ewoc &optional (start-node (ewoc-nth ewoc 0 )) (end-node (ewoc-nth ewoc -1 )))
26732677 ; ; TODO: Use this in appropriate places.
26742678 " Insert sender headers into current buffer's `ement-ewoc' .
26752679Inserts headers between START-NODE and END-NODE, which default to
26762680the first and last nodes in the buffer, respectively."
2677- (let* ((ewoc ement-ewoc)
2678- (end-pos (ewoc-location (or end-node
2679- (ewoc-nth ewoc -1 ))))
2680- (node-b (or start-node (ewoc-nth ewoc 0 )))
2681- (type-predicate (lambda (node-data )
2682- (pcase node-data
2683- ((pred ement-event-p) t )
2684- (`(ts . , _ ) t ))))
2685- node-a)
2686- ; ; On the first loop iteration, node-a is set to the first matching
2687- ; ; node after node-b; then it's set to the first node after node-a.
2688- (while (and (setf node-a (ement-room--ewoc-next-matching ewoc (or node-a node-b) type-predicate)
2689- node-b (when node-a
2690- (ement-room--ewoc-next-matching ewoc node-a type-predicate)))
2691- (not (or (> (ewoc-location node-a) end-pos)
2692- (> (ewoc-location node-b) end-pos))))
2693- ; ; This starts to get a little messy, accounting for the
2694- ; ; different types of nodes. EIEIO would probably help here.
2695- (let ((a-data (ewoc-data node-a))
2696- (b-data (ewoc-data node-b)))
2697- (cond ((and (ement-event-p b-data)
2698- (equal " m.room.member" (ement-event-type b-data)))
2699- ; ; B is a membership event: don't insert sender header.
2700- nil )
2701- ((when-let ((node-after-a (ewoc-next ewoc node-a)))
2702- (pcase (ewoc-data node-after-a)
2703- ((or (pred ement-user-p)
2704- 'ement-room-fully-read-marker
2705- 'ement-room-read-receipt-marker )
2706- t )))
2707- ; ; Node after A is a sender header: don't insert another.
2708- nil )
2709- ((and (ement-event-p a-data)
2710- (ement-event-p b-data)
2711- (equal (ement-event-sender a-data)
2712- (ement-event-sender b-data)))
2713- ; ; Each node is an event and their senders are the same: don't insert another header.
2714- nil )
2715- ((ement-event-p b-data)
2716- ; ; Node B is an event with a different sender: insert header.
2717- (ewoc-enter-before ewoc node-b (ement-event-sender b-data))))))))
2681+ (cl-labels ((read-marker-p
2682+ (data) (member data '(ement-room-fully-read-marker
2683+ ement-room-read-receipt-marker)))
2684+ (message-event-p
2685+ (data) (and (ement-event-p data)
2686+ (equal " m.room.message" (ement-event-type data))))
2687+ (insert-sender-before
2688+ (node) (ewoc-enter-before ewoc node (ement-event-sender (ewoc-data node)))))
2689+ (let* ((event-node (if (ement-event-p (ewoc-data start-node))
2690+ start-node
2691+ (ement-room--ewoc-next-matching ewoc start-node
2692+ #'ement-event-p )))
2693+ (prev-node (when event-node
2694+ ; ; Just in case...
2695+ (ewoc-prev ewoc event-node))))
2696+ (while (and event-node
2697+ ; ; I don't like looking up the location of these nodes on every loop
2698+ ; ; iteration, but it seems like the only reliable way to determine
2699+ ; ; whether we've reached the end node. However, when this function is
2700+ ; ; called for short batches of events (or even a single event, like when
2701+ ; ; called from `ement-room--insert-event' ), the overhead should be
2702+ ; ; minimal.
2703+ (<= (ewoc-location event-node) (ewoc-location end-node)))
2704+ (when (message-event-p (ewoc-data event-node))
2705+ (if (not prev-node)
2706+ ; ; No previous node and event is a message: insert header.
2707+ (insert-sender-before event-node)
2708+ ; ; Previous node exists.
2709+ (when (read-marker-p prev-node)
2710+ ; ; Previous node is a read marker: we want to act as if they don't exist, so
2711+ ; ; we set `prev-node' to the non-marker node before it.
2712+ (setf prev-node (ement-room--ewoc-next-matching ewoc prev-node
2713+ (lambda (data )
2714+ (not (read-marker-p data))))))
2715+ (when prev-node
2716+ ; ; A previous node still exists: maybe we need to add a header.
2717+ (cl-typecase (ewoc-data prev-node)
2718+ (ement-event
2719+ ; ; Previous node is an event.
2720+ (when (and (message-event-p (ewoc-data prev-node))
2721+ (not (equal (ement-event-sender (ewoc-data prev-node))
2722+ (ement-event-sender (ewoc-data event-node)))))
2723+ ; ; Previous node is a message event with a different sender: insert
2724+ ; ; header.
2725+ (insert-sender-before event-node)))
2726+ ((or ement-user ement-room-membership-events)
2727+ ; ; Previous node is a user or coalesced membership events: do not insert
2728+ ; ; header.
2729+ nil )
2730+ (t
2731+ ; ; Previous node is not an event and not a read marker: insert header.
2732+ (insert-sender-before event-node))))))
2733+ (setf event-node (ement-room--ewoc-next-matching ewoc event-node
2734+ #'ement-event-p )
2735+ prev-node (when event-node
2736+ (ewoc-prev ewoc event-node)))))))
27182737
27192738(defun ement-room--coalesce-nodes (a b ewoc )
2720- " Try to coalesce events in nodes A and B in EWOC, returning non-nil if done."
2739+ " Try to coalesce events in nodes A and B in EWOC, returning absorbing node if done."
27212740 (cl-labels ((coalescable-p
27222741 (node) (or (and (ement-event-p (ewoc-data node))
27232742 (member (ement-event-type (ewoc-data node)) '(" m.room.member" )))
@@ -2736,7 +2755,7 @@ the first and last nodes in the buffer, respectively."
27362755 (ement-room-membership-events--update (ewoc-data absorbing-node))
27372756 (ewoc-delete ewoc absorbed-node)
27382757 (ewoc-invalidate ewoc absorbing-node)
2739- t ))))
2758+ absorbing-node ))))
27402759
27412760(defun ement-room--insert-event (event )
27422761 " Insert EVENT into current buffer."
@@ -2813,55 +2832,14 @@ the first and last nodes in the buffer, respectively."
28132832 (ewoc-enter-after ewoc event-node-before event)))
28142833 (when ement-room-coalesce-events
28152834 ; ; Try to coalesce events.
2816- (or (when event-node-before
2817- (ement-room--coalesce-nodes event-node-before new-node ewoc))
2818- (when (ewoc-next ewoc new-node)
2819- (ement-room--coalesce-nodes new-node (ewoc-next ewoc new-node) ewoc))))
2820- (when ement-room-sender-headers
2821- ; ; Insert header for new event when necessary.
2822- ; ; TODO: Make `ement-room--insert-sender-headers' work for this case and use it
2823- ; ; instead, because this seems to duplicate functionality. (It almost works now.)
2824- (cond ((not event-node-before)
2825- (ement-debug " No event before: Add sender before new node." )
2826- (ewoc-enter-before ewoc new-node (ement-event-sender event)))
2827- ; ; There exists an event node before the new one: check the node immediately
2828- ; ; before the new one (which may not be an event).
2829- ((let* ((ignored-node-data-preds
2830- '((lambda (data )
2831- (pcase data
2832- ((or 'ement-room-fully-read-marker
2833- 'ement-room-read-receipt-marker )
2834- t )))
2835- (lambda (data )
2836- (pcase data
2837- (`(ts . , _ )
2838- t )))
2839- (lambda (data )
2840- (and (ement-event-p data)
2841- (pcase (ement-event-type data)
2842- ((or " m.room.member" " m.room.invite" )
2843- t ))))))
2844- (event-node-before (cl-loop with start-node = new-node
2845- for node = (ewoc-prev ewoc start-node)
2846- while node
2847- do (setf start-node node)
2848- unless (cl-loop for pred in ignored-node-data-preds
2849- thereis (funcall pred (ewoc-data node)))
2850- when (ement-event-p (ewoc-data node))
2851- return node)))
2852- (when event-node-before
2853- (ement-debug " Event node before new node: compare sender." )
2854- (cond ((equal (ement-event-sender event)
2855- (ement-event-sender (ewoc-data event-node-before)))
2856- (ement-debug " Event node before new node has same sender: don't insert header." ))
2857- (t
2858- (ement-debug " Event node before new node has different sender: insert header." )
2859- (ewoc-enter-before ewoc new-node (ement-event-sender event))))))))
2860- ; ; Insert header for event after new event when necessary.
2861- (when-let ((next-event-node (find-node-if ewoc #'ement-event-p :start new-node :move #'ewoc-next )))
2862- (unless (equal (ement-event-sender event) (ement-event-sender (ewoc-data next-event-node)))
2863- (ement-debug " Event after from different sender: insert its sender before it." )
2864- (ewoc-enter-before ewoc next-event-node (ement-event-sender (ewoc-data next-event-node))))))
2835+ ; ; TODO: Move this to a separate function and call it from where this function is called.
2836+ (setf new-node (or (when event-node-before
2837+ (ement-room--coalesce-nodes event-node-before new-node ewoc))
2838+ (when (ewoc-next ewoc new-node)
2839+ (ement-room--coalesce-nodes new-node (ewoc-next ewoc new-node) ewoc))
2840+ new-node)))
2841+ (when ement-room-sender-in-headers
2842+ (ement-room--insert-sender-headers ewoc new-node new-node))
28652843 ; ; Return new node.
28662844 new-node)))
28672845
0 commit comments