From da436bf39ee7563371281f72b33b7e43a9268a12 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 1 Dec 2020 00:28:13 -0600 Subject: [PATCH] Loading earlier messages, etc. --- ement-room.el | 74 ++++++++++++++++++++++++++++++++++++++++++------ ement-structs.el | 2 +- ement.el | 3 +- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/ement-room.el b/ement-room.el index 62e395c..dd0c9e0 100644 --- a/ement-room.el +++ b/ement-room.el @@ -49,6 +49,7 @@ (define-key map (kbd "g") #'ement-room-sync) (define-key map (kbd "v") #'ement-room-view-event) (define-key map (kbd "RET") #'ement-room-send-message) + (define-key map [remap scroll-down-command] #'ement-room-scroll-down-command) map) "Keymap for Ement room buffers.") @@ -73,16 +74,74 @@ See function `format-time-string'." (const " [%Y-%m-%d %H:%M:%S]") string)) +(defcustom ement-room-username-display-property '(raise -0.25) + "Display property applied to username strings. +See Info node `(elisp)Other Display Specs'." + :type '(choice (list :tag "Raise" (const raise :tag "Raise") (number :tag "Factor")) + (list :tag "Height" (const height) + (choice (list :tag "Larger" (const + :tag "Larger") (number :tag "Steps")) + (list :tag "Smaller" (const - :tag "Smaller") (number :tag "Steps")) + (number :tag "Factor") + (function :tag "Function") + (sexp :tag "Form"))) )) + (defface ement-room-timestamp - '((t (:inherit font-lock-variable-name-face))) + '((t (:inherit font-lock-comment-face))) "Event timestamps.") (defface ement-room-user - '((t (:inherit font-lock-keyword-face))) + '((t (:inherit font-lock-function-name-face :weight bold))) "Usernames.") ;;;; Commands +(defun ement-room-scroll-down-command () + "Scroll down, and load NUMBER older messages when at top." + (interactive) + (condition-case _err + (scroll-down nil) + (beginning-of-buffer + (message "Loading earlier messages...") + (call-interactively #'ement-room-retro)))) + +(defun ement-room-retro (session room number) + "Retrieve NUMBER older messages in ROOM on SESSION." + (interactive (list ement-session ement-room + (if current-prefix-arg + (read-number "Number of messages: ") + 10))) + (pcase-let* (((cl-struct ement-session server token) session) + ((cl-struct ement-server hostname port) server) + ((cl-struct ement-room id prev-batch) room) + (endpoint (format "rooms/%s/messages" (url-hexify-string id)))) + (ement-api hostname port token endpoint + (apply-partially #'ement-room-retro-callback room) + :params (list (list "from" prev-batch) + (list "dir" "b") + (list "limit" (number-to-string number)))))) + +(defun ement-room-retro-callback (room data) + "Push new DATA to ROOM on SESSION and add events to room buffer." + (pcase-let* (((cl-struct ement-room) room) + ((map _start end chunk state) data) + (buffer (cl-loop for buffer in (buffer-list) + when (equal room (buffer-local-value 'ement-room buffer)) + return buffer))) + ;; FIXME: These are pushed onto the front of the lists. Doesn't + ;; really matter, but maybe better to put them at the other end. + (cl-loop for event across state + ;; FIXME: Need to use make-event + do (push event (ement-room-state room))) + (cl-loop for event across-ref chunk + do (setf event (ement--make-event event)) + (push event (ement-room-timeline room))) + (when buffer + (with-current-buffer buffer + (cl-loop for event across chunk + do (ement-room--insert-event event)))) + (setf (ement-room-prev-batch room) end))) + + ;; FIXME: What is the best way to do this, with ement--sync being in another file? (declare-function ement--sync "ement.el") (defun ement-room-sync (session) @@ -200,12 +259,11 @@ To be used as the pretty-printer for `ewoc-create'." (defun ement-room--format-user (user) "Format `ement-user' USER for current buffer's room." - (propertize - " " 'display `((margin left-margin) - ,(propertize (or (gethash ement-room (ement-user-room-display-names user)) - (puthash ement-room (ement-room--user-display-name user ement-room) - (ement-user-room-display-names user))) - 'face 'ement-room-user)))) + (propertize (or (gethash ement-room (ement-user-room-display-names user)) + (puthash ement-room (ement-room--user-display-name user ement-room) + (ement-user-room-display-names user))) + 'display ement-room-username-display-property + 'face 'ement-room-user)) (defun ement-room--user-display-name (user room) "Return the displayname for USER in ROOM." diff --git a/ement-structs.el b/ement-structs.el index 41db599..819ccd6 100644 --- a/ement-structs.el +++ b/ement-structs.el @@ -44,7 +44,7 @@ user server token transaction-id rooms next-batch) (cl-defstruct ement-room - id display-name + id display-name prev-batch summary state timeline timeline* ephemeral account-data unread-notifications) ;;;; Variables diff --git a/ement.el b/ement.el index d8cd636..7ae1a17 100644 --- a/ement.el +++ b/ement.el @@ -251,7 +251,8 @@ To be called in `ement-sync-callback-hook'." (progress-reporter-update ement-progress-reporter (cl-incf ement-progress-value))) (cl-loop for event across (alist-get 'events timeline) do (push (ement--make-event event) (ement-room-timeline* room)) - (progress-reporter-update ement-progress-reporter (cl-incf ement-progress-value))))) + (progress-reporter-update ement-progress-reporter (cl-incf ement-progress-value))) + (setf (ement-room-prev-batch room) (alist-get 'prev_batch timeline)))) (defvar ement-users (make-hash-table :test #'equal) ;; NOTE: When changing the ement-user struct, it's necessary to