From 351aea840efb67336035a5869cce9a7331a1c6fe Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 23 Sep 2023 21:23:36 -0500 Subject: [PATCH] Fix: Writing reply from compose buffer from minibuffer Fixes #189. Reported-by: Phil Sainty --- ement-room.el | 81 +++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/ement-room.el b/ement-room.el index 708ceb8e..e01887f5 100644 --- a/ement-room.el +++ b/ement-room.el @@ -97,6 +97,10 @@ to sort events and update other slots." "Non-nil when earlier messages are being loaded. Used to avoid overlapping requests.") +(defvar-local ement-room-editing-event nil + "When non-nil, the user is editing this event. +Used by `ement-room-send-message'.") + (defvar-local ement-room-replying-to-event nil "When non-nil, the user is replying to this event. Used by `ement-room-send-message'.") @@ -706,14 +710,13 @@ number (to darken rather than lighten)." (declare (indent 1)) `(let* ((node (ewoc-locate ement-ewoc ,position)) (event (ewoc-data node)) - ement-room-replying-to-event ement-room-replying-to-overlay) + ement-room-replying-to-overlay) (unless (and (ement-event-p event) (ement-event-id event)) (error "No event at point")) (unwind-protect (progn - (setf ement-room-replying-to-event event - ement-room-replying-to-overlay + (setf ement-room-replying-to-overlay (make-overlay (ewoc-location node) ;; NOTE: It doesn't seem possible to get the end position of ;; a node, so if there is no next node, we use point-max. @@ -725,8 +728,7 @@ number (to darken rather than lighten)." ,@body) (when (overlayp ement-room-replying-to-overlay) (delete-overlay ement-room-replying-to-overlay)) - (setf ement-room-replying-to-event nil - ement-room-replying-to-overlay nil)))) + (setf ement-room-replying-to-overlay nil)))) (defmacro ement-room-with-typing (&rest body) "Send typing notifications around BODY. @@ -1702,7 +1704,8 @@ The message must be one sent by the local user." ((cl-struct ement-session user events) ement-session) ((cl-struct ement-event sender id (content (map body ('m.relates_to relates-to)))) - event)) + event) + (ement-room-editing-event event)) (unless (equal (ement-user-id sender) (ement-user-id user)) (user-error "You may only edit your own messages")) (when relates-to @@ -1748,23 +1751,24 @@ The message must be one sent by the local user." (user-error "Message not deleted")))) (ement-redact event room session reason)) -(defun ement-room-write-reply () - "Send a reply to event at point." - (interactive) +(defun ement-room-write-reply (event) + "Write and send a reply to EVENT. +Interactively, to event at point." + (interactive (list (ewoc-data (ewoc-locate ement-ewoc)))) (cl-assert ement-ewoc) (cl-assert ement-room) (cl-assert ement-session) - (cl-assert (ement-event-p (ewoc-data (ewoc-locate ement-ewoc)))) - (ement-room-with-highlighted-event-at (point) - (pcase-let* ((event (ewoc-data (ewoc-locate ement-ewoc))) - (room ement-room) - (session ement-session) - (prompt (format "Send reply (%s): " (ement-room-display-name room))) - (ement-room-read-string-setup-hook - (lambda () - (setq-local ement-room-replying-to-event event))) - (body (ement-room-with-typing - (ement-room-read-string prompt nil 'ement-room-message-history - nil 'inherit-input-method)))) - (ement-room-send-message room session :body body :replying-to-event event)))) + (cl-assert (ement-event-p event)) + (let ((ement-room-replying-to-event event)) + (ement-room-with-highlighted-event-at (point) + (pcase-let* ((room ement-room) + (session ement-session) + (prompt (format "Send reply (%s): " (ement-room-display-name room))) + (ement-room-read-string-setup-hook + (lambda () + (setq-local ement-room-replying-to-event event))) + (body (ement-room-with-typing + (ement-room-read-string prompt nil 'ement-room-message-history + nil 'inherit-input-method)))) + (ement-room-send-message room session :body body :replying-to-event event))))) (defun ement-room-send-reaction (key position) "Send reaction of KEY to event at POSITION. @@ -3676,6 +3680,7 @@ To be called from a minibuffer opened from (input-method current-input-method) ; Capture this value from the minibuffer. (send-message-filter ement-room-send-message-filter) (replying-to-event ement-room-replying-to-event) + (editing-event ement-room-editing-event) (compose-fn (lambda () ;; HACK: Since exiting the minibuffer restores the previous window configuration, ;; we have to do some magic to get the new compose buffer to appear. @@ -3685,13 +3690,16 @@ To be called from a minibuffer opened from (ement-room-compose-message ement-room ement-session :body body) ;; FIXME: This doesn't propagate the send-message-filter to the minibuffer. (setf ement-room-send-message-filter send-message-filter) - (setq-local ement-room-replying-to-event replying-to-event) - (when replying-to-event - (setq-local header-line-format - (concat header-line-format - (format " (Replying to message from %s)" - (ement--user-displayname-in - ement-room (ement-event-sender replying-to-event)))))) + (setq-local ement-room-replying-to-event replying-to-event + ement-room-editing-event editing-event) + (cond (replying-to-event + (setq-local header-line-format + (concat header-line-format + (format " (Replying to message from %s)" + (ement--user-displayname-in + ement-room (ement-event-sender replying-to-event)))))) + (editing-event + (setq-local header-line-format (concat header-line-format " (Editing message)")))) (let* ((compose-buffer (current-buffer)) (show-buffer-fn-symbol (gensym "ement-show-compose-buffer")) (show-buffer-fn (lambda () @@ -3721,23 +3729,26 @@ To be called from an `ement-room-compose' buffer." (session ement-session) (input-method current-input-method) (send-message-filter ement-room-send-message-filter) - (replying-to-event ement-room-replying-to-event)) + (replying-to-event ement-room-replying-to-event) + (editing-event ement-room-editing-event)) (quit-restore-window nil 'kill) (ement-view-room room session) (let* ((prompt (format "Send message (%s): " (ement-room-display-name ement-room))) (current-input-method input-method) ; Bind around read-string call. (ement-room-send-message-filter send-message-filter) - (pos (when replying-to-event + (pos (when (or editing-event replying-to-event) (ewoc-location (ement-room--ewoc-last-matching ement-ewoc (lambda (data) - (eq data replying-to-event)))))) - (body (if replying-to-event + (eq data (or editing-event replying-to-event))))))) + (body (if (or editing-event replying-to-event) (ement-room-with-highlighted-event-at pos (ement-room-read-string prompt (car kill-ring) 'ement-room-message-history nil 'inherit-input-method)) (ement-room-read-string prompt (car kill-ring) 'ement-room-message-history - nil 'inherit-input-method)) )) - (ement-room-send-message ement-room ement-session :body body :replying-to-event replying-to-event)))) + nil 'inherit-input-method)))) + (if editing-event + (ement-room-edit-message editing-event ement-room ement-session body) + (ement-room-send-message ement-room ement-session :body body :replying-to-event replying-to-event))))) (defun ement-room-init-compose-buffer (room session) "Eval BODY, setting up the current buffer as a compose buffer.