Skip to content

Commit e52c5a7

Browse files
committed
Merge: Support downloading media
See #323.
2 parents ebc04f1 + effc225 commit e52c5a7

File tree

2 files changed

+75
-8
lines changed

2 files changed

+75
-8
lines changed

README.org

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ Ement.el doesn't support encrypted rooms natively, but it can be used transparen
301301

302302
*Additions*
303303

304+
+ Command ~ement-room-download-file~, which downloads the file in the event at point (for image, audio, video, and file messages). ([[https://github.com/alphapapa/ement.el/pull/323][#323]]. Thanks to [[https://github.com/viiru-][Arto Jantunen]].)
304305
+ Customization groups for faces. (Thanks to [[https://github.com/phil-s][Phil Sainty]].)
305306
+ Option ~ement-room-hide-redacted-message-content~, which hides the content of redacted messages by default. It may be disabled to keep redacted content visible with a strikethrough face, which may be useful for room moderators, but users should keep in mind that doing so will leave unpleasant content visible in the current session, even after being redacted by moderators.
306307
+ Option ~ement-room-list-avatars-generation~: if disabled, SVG-based room avatars are not generated. This option automatically tests whether SVG support is available in Emacs, and should allow use with builds of Emacs that lack =librsvg= support.
@@ -309,6 +310,10 @@ Ement.el doesn't support encrypted rooms natively, but it can be used transparen
309310

310311
+ Disable underline for faces ~ement-room-list-direct~ and ~ement-room-list-name~ (in case a face they inherit from enables it, e.g. when themed).
311312

313+
*Fixes*
314+
315+
+ Call ~eww-browse-url~ instead of ~browse-url~ in ~ement-room-browse-mxc~ (because the latter is not useful for authenticated media if the user has configured it to use a different browser). ([[https://github.com/alphapapa/ement.el/pull/323][#323]]. Thanks to [[https://github.com/viiru-][Arto Jantunen]].)
316+
312317
** 0.16
313318

314319
*Compatibility*

ement-room.el

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ keymap directly the issue may be visible.")
195195
(define-key map (kbd "s f") #'ement-room-send-file)
196196
(define-key map (kbd "s i") #'ement-room-send-image)
197197
(define-key map (kbd "v") #'ement-room-view-event)
198+
(define-key map (kbd "D") #'ement-room-download-file)
198199

199200
;; Users
200201
(define-key map (kbd "u RET") #'ement-send-direct-message)
@@ -2502,6 +2503,17 @@ To be used in `ement-room-view-hook', which see."
25022503
(goto-char (ewoc-location node))
25032504
(error "Event not found in buffer: %S" (ement-event-id event))))
25042505

2506+
(defun ement-room--event-at (pos)
2507+
"Return event at POS or signal an error."
2508+
;; TODO: Use this where appropriate.
2509+
(save-excursion
2510+
(goto-char pos)
2511+
(cl-assert ement-ewoc)
2512+
(let ((data (ewoc-data (ewoc-locate ement-ewoc))))
2513+
(cl-typecase data
2514+
(ement-event data)
2515+
(otherwise (user-error "No event at point"))))))
2516+
25052517
(cl-defun ement-room-retro-callback (room session data
25062518
&key (set-prev-batch t))
25072519
"Push new DATA to ROOM on SESSION and add events to room buffer.
@@ -5546,9 +5558,9 @@ Then invalidate EVENT's node to show the image."
55465558
(file-size-human-readable size)))
55475559
(string (format "[file: %s (%s) (%s)]" filename mimetype human-size)))
55485560
(concat (propertize string
5549-
'action #'ement-room-browse-mxc
5561+
'action #'ement-room-download-file
55505562
'button t
5551-
'button-data mxc-url
5563+
'button-data event
55525564
'category t
55535565
'face 'button
55545566
'follow-link t
@@ -5569,9 +5581,9 @@ Then invalidate EVENT's node to show the image."
55695581
(human-size (file-size-human-readable size))
55705582
(string (format "[video: %s (%s) (%sx%s) (%s)]" body mimetype w h human-size)))
55715583
(concat (propertize string
5572-
'action #'ement-room-browse-mxc
5584+
'action #'ement-room-download-file
55735585
'button t
5574-
'button-data mxc-url
5586+
'button-data event
55755587
'category t
55765588
'face 'button
55775589
'follow-link t
@@ -5592,9 +5604,9 @@ Then invalidate EVENT's node to show the image."
55925604
(human-duration (format-seconds "%m:%s" (/ duration 1000)))
55935605
(string (format "[audio: %s (%s) (%s) (%s)]" body mimetype human-duration human-size)))
55945606
(concat (propertize string
5595-
'action #'ement-room-browse-mxc
5607+
'action #'ement-room-download-file
55965608
'button t
5597-
'button-data mxc-url
5609+
'button-data event
55985610
'category t
55995611
'face 'button
56005612
'follow-link t
@@ -5833,7 +5845,8 @@ For use in `completion-at-point-functions'."
58335845
("s r" "Send reaction" ement-room-send-reaction)
58345846
("s e" "Send emote" ement-room-send-emote)
58355847
("s f" "Send file" ement-room-send-file)
5836-
("s i" "Send image" ement-room-send-image)]
5848+
("s i" "Send image" ement-room-send-image)
5849+
("D" "Download event media" ement-room-download-file)]
58375850
["Users"
58385851
("u RET" "Send direct message" ement-send-direct-message)
58395852
("u i" "Invite user" ement-invite-user)
@@ -5933,7 +5946,56 @@ For use in `completion-at-point-functions'."
59335946
(decode-coding-region (point-min) (point) 'utf-8)
59345947
;; HACK: This STATUS argument to `eww-render' is bogus.
59355948
(apply callback 'status cbargs))))))
5936-
(browse-url mxc))))
5949+
(eww-browse-url mxc))))
5950+
5951+
;;;; Downloading media/files
5952+
5953+
(defvar eww-download-directory)
5954+
5955+
(defun ement-room-download-file (event destination)
5956+
"Download EVENT's file to DESTINATION.
5957+
If DESTINATION is a directory, use the file's default name;
5958+
otherwise, download to the filename. Interactively, download to
5959+
`eww-download-directory'; with prefix, prompt for destination."
5960+
(interactive (list (ement-room--event-at (point))
5961+
(if current-prefix-arg
5962+
(expand-file-name
5963+
(read-file-name
5964+
"Download to: "
5965+
(cl-typecase eww-download-directory
5966+
(string eww-download-directory)
5967+
(function (funcall eww-download-directory)))))
5968+
(expand-file-name
5969+
(cl-typecase eww-download-directory
5970+
(string eww-download-directory)
5971+
(function (funcall eww-download-directory)))))))
5972+
(pcase-let (((cl-struct ement-event
5973+
(content (map ('filename event-filename)
5974+
('url mxc-url))))
5975+
event)
5976+
(started-at (current-time)))
5977+
(when (directory-name-p destination)
5978+
(unless (file-exists-p destination)
5979+
(make-directory destination 'parents))
5980+
(setf destination (file-name-concat destination event-filename)))
5981+
(unless (file-writable-p destination)
5982+
(user-error "Destination path not writable: %S" destination))
5983+
(when (file-exists-p destination)
5984+
(user-error "File already exists: %S" destination))
5985+
;; TODO: For bonus points, provide a way to cancel a download (otherwise the user
5986+
;; would have to use `list-processes' and find the right one to delete), and to see
5987+
;; progress (perhaps borrowing some of the relevant code in hyperdrive.el).
5988+
(ement--media-request mxc-url ement-session :authenticatedp t
5989+
:as `(file ,destination)
5990+
:then (lambda (&rest _)
5991+
(let* ((file-size (file-attribute-size
5992+
(file-attributes destination)))
5993+
(duration (float-time (time-subtract (current-time) started-at)))
5994+
(speed (file-size-human-readable (/ file-size duration))))
5995+
(message "File downloaded: %S (%s in %s at %s/sec) "
5996+
destination (file-size-human-readable file-size)
5997+
(format-seconds "%h:%m:%s%z seconds" duration)
5998+
speed))))))
59375999

59386000
;;;; Footer
59396001

0 commit comments

Comments
 (0)