aboutsummaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authormousebot <mousebot@riseup.net>2022-02-14 16:15:04 +0100
committermousebot <mousebot@riseup.net>2022-02-14 16:15:04 +0100
commit3e80d32fbce9a242c1f7080effbff3dcab5a9871 (patch)
tree6a47223fee981b884b10885130dcae987dd80314 /lisp
parent949520069569b3b5397a00cca0d9671f3445ddea (diff)
parent6e68b7051595bf99bade4d3052286f95d606a155 (diff)
Merge branch 'develop' into filters
Diffstat (limited to 'lisp')
-rw-r--r--lisp/mastodon-media.el16
-rw-r--r--lisp/mastodon-search.el1
-rw-r--r--lisp/mastodon-tl.el180
-rw-r--r--lisp/mastodon-toot.el11
-rw-r--r--lisp/mastodon.el21
5 files changed, 171 insertions, 58 deletions
diff --git a/lisp/mastodon-media.el b/lisp/mastodon-media.el
index 4e4a15d..9441bdb 100644
--- a/lisp/mastodon-media.el
+++ b/lisp/mastodon-media.el
@@ -272,6 +272,20 @@ Replace them with the referenced image."
(put-text-property start end 'media-state 'loading)
(mastodon-media--load-image-from-url
image-url media-type start (- end start))))))))
+ ;; (mastodon-media--moving-image-overlay start end)))))))
+
+;; (defun mastodon-media--moving-image-overlay (start end)
+;; "Add play symbol overlay to moving image media items."
+;; (let ((ov (make-overlay start end))
+;; (type (get-text-property start 'mastodon-media-type)))
+;; (when (or (equal type "gifv")
+;; (equal type "video"))
+;; (overlay-put
+;; ov
+;; 'after-string
+;; (propertize " "
+;; 'face
+;; '((:height 1.5 :inherit 'font-lock-comment-face)))))))
(defun mastodon-media--get-avatar-rendering (avatar-url)
"Return the string to be written that renders the avatar at AVATAR-URL."
@@ -312,7 +326,7 @@ TYPE is the attachment's type field on the server."
'keymap mastodon-tl--shr-image-map-replacement
'help-echo (if (string= type "image")
help-echo
- (concat help-echo "\ntype: " type)))
+ (concat help-echo "\nC-RET: play " type " with mpv")))
" ")))
(provide 'mastodon-media)
diff --git a/lisp/mastodon-search.el b/lisp/mastodon-search.el
index 8c654cc..d17b054 100644
--- a/lisp/mastodon-search.el
+++ b/lisp/mastodon-search.el
@@ -39,6 +39,7 @@
(autoload 'mastodon-tl--as-string "mastodon-tl")
(autoload 'mastodon-auth--access-token "mastodon-auth")
(autoload 'mastodon-http--get-search-json "mastodon-http")
+(autoload 'mastodon-http--api "mastodon-http")
(defvar mastodon-instance-url)
(defvar mastodon-tl--link-keymap)
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index a87fc2e..d69cb1a 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -36,6 +36,8 @@
(require 'time-date)
(require 'cl-lib) ; for cl-mapcar
+(require 'mpv nil :no-error)
+
(autoload 'mastodon-auth--get-account-name "mastodon-auth")
(autoload 'mastodon-http--api "mastodon-http")
(autoload 'mastodon-http--get-json "mastodon-http")
@@ -61,6 +63,9 @@
(autoload 'mastodon-notifications--get "mastodon-notifications"
"Display NOTIFICATIONS in buffer." t) ; interactive
(autoload 'mastodon-search--insert-users-propertized "mastodon-search")
+(autoload 'mastodon-search--get-user-info "mastodon-search")
+(when (require 'mpv nil :no-error)
+ (declare-function mpv-start "mpv"))
(defvar mastodon-instance-url)
(defvar mastodon-toot-timestamp-format)
(defvar shr-use-fonts) ;; declare it since Emacs24 didn't have this
@@ -156,6 +161,7 @@ types of mastodon links and not just shr.el-generated ones.")
(define-key map (kbd "u") 'mastodon-tl--update)
;; keep new my-profile binding; shr 'O' doesn't work here anyway
(define-key map (kbd "O") 'mastodon-profile--my-profile)
+ (define-key map (kbd "<C-return>") 'mastodon-tl--mpv-play-video-at-point)
(keymap-canonicalize map))
"The keymap to be set for shr.el generated image links.
@@ -168,6 +174,14 @@ types of mastodon links and not just shr.el-generated ones.")
(keymap-canonicalize map))
"Keymap for viewing filters.")
+(defvar mastodon-tl--byline-link-keymap
+ (when (require 'mpv nil :no-error)
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "<C-return>") 'mastodon-tl--mpv-play-video-from-byline)
+ (keymap-canonicalize map)))
+ "The keymap to be set for the author byline.
+The idea is that you can play media without navigating to it.")
+
(defun mastodon-tl--next-tab-item ()
"Move to the next interesting item.
@@ -298,6 +312,9 @@ Optionally start from POS."
(mastodon-media--get-avatar-rendering avatar-url))
(propertize name
'face 'mastodon-display-name-face
+ ;; enable playing of videos when point is on byline:
+ 'attachments (mastodon-tl--get-attachments-for-byline toot)
+ 'keymap mastodon-tl--byline-link-keymap
;; echo faves count when point on post author name:
;; which is where --goto-next-toot puts point.
'help-echo
@@ -306,29 +323,61 @@ Optionally start from POS."
(propertize (concat "@" handle)
'face 'mastodon-handle-face
'mouse-face 'highlight
- ;; TODO: Replace url browsing with native profile viewing
- 'mastodon-tab-stop 'user-handle
+ 'mastodon-tab-stop 'user-handle
'account account
- 'shr-url profile-url
- 'keymap mastodon-tl--link-keymap
+ 'shr-url profile-url
+ 'keymap mastodon-tl--link-keymap
'mastodon-handle (concat "@" handle)
- 'help-echo (concat "Browse user profile of @" handle))
+ 'help-echo (concat "Browse user profile of @" handle))
")")))
(defun mastodon-tl--format-faves-count (toot)
"Format a favorites, boosts, replies count for a TOOT.
-Used to help-echo when point is at the start of a byline,
-i.e. where `mastodon-tl--goto-next-toot' leaves point."
- (let ((toot-to-count
- (or
- ;; simply praying this order works
- (alist-get 'status toot) ; notifications timeline
- (alist-get 'reblog toot) ; boosts
- toot))) ; everything else
- (format "%s faves | %s boosts | %s replies"
- (alist-get 'favourites_count toot-to-count)
- (alist-get 'reblogs_count toot-to-count)
- (alist-get 'replies_count toot-to-count))))
+Used as a help-echo when point is at the start of a byline, i.e.
+where `mastodon-tl--goto-next-toot' leaves point. Also displays a
+toot's media types and optionally the binding to play moving
+image media from the byline."
+ (let* ((toot-to-count
+ (or
+ ;; simply praying this order works
+ (alist-get 'status toot) ; notifications timeline
+ (alist-get 'reblog toot) ; boosts
+ toot)) ; everything else
+ (media-types (mastodon-tl--get-media-types toot))
+ (format-faves (format "%s faves | %s boosts | %s replies"
+ (alist-get 'favourites_count toot-to-count)
+ (alist-get 'reblogs_count toot-to-count)
+ (alist-get 'replies_count toot-to-count)))
+ (format-media (when media-types
+ (format " | media: %s"
+ (mapconcat #'identity media-types " "))))
+ (format-media-binding (when (and (or
+ (member "video" media-types)
+ (member "gifv" media-types))
+ (require 'mpv nil :no-error))
+ (format " | C-RET to view with mpv"))))
+ (format "%s" (concat format-faves format-media format-media-binding))))
+
+(defun mastodon-tl--get-media-types (toot)
+ "Return a list of the media attachment types of the TOOT at point."
+ (let* ((attachments (mastodon-tl--field 'media_attachments toot)))
+ (mapcar (lambda (x)
+ (alist-get 'type x))
+ attachments)))
+
+(defun mastodon-tl--get-attachments-for-byline (toot)
+ "Return a list of attachment URLs and types for TOOT.
+The result is added as an attachments property to author-byline."
+ (let ((media-attachments (mastodon-tl--field 'media_attachments toot)))
+ (mapcar
+ (lambda (attachement)
+ (let ((remote-url
+ (or (alist-get 'remote_url attachement)
+ ;; fallback b/c notifications don't have remote_url
+ (alist-get 'url attachement)))
+ (type (alist-get 'type attachement)))
+ `(:url ,remote-url :type ,type)))
+ media-attachments)))
(defun mastodon-tl--byline-boosted (toot)
"Add byline for boosted data from TOOT."
@@ -415,9 +464,9 @@ TIME-STAMP is assumed to be in the past."
(defun mastodon-tl--byline (toot author-byline action-byline)
"Generate byline for TOOT.
-AUTHOR-BYLINE is function for adding the author portion of
+AUTHOR-BYLINE is a function for adding the author portion of
the byline that takes one variable.
-ACTION-BYLINE is a function for adding an action, such as boosting
+ACTION-BYLINE is a function for adding an action, such as boosting,
favouriting and following to the byline. It also takes a single function.
By default it is `mastodon-tl--byline-boosted'"
(let ((parsed-time (date-to-time (mastodon-tl--field 'created_at toot)))
@@ -425,20 +474,19 @@ By default it is `mastodon-tl--byline-boosted'"
(boosted (equal 't (mastodon-tl--field 'reblogged toot)))
(visibility (mastodon-tl--field 'visibility toot)))
(concat
- ;; (propertize "\n | " 'face 'default)
- (propertize
+ ;; Boosted/favourited markers are not technically part of the byline, so
+ ;; we don't propertize them with 'byline t', as per the rest. This
+ ;; ensures that `mastodon-tl--goto-next-toot' puts point on
+ ;; author-byline, not before the (F) or (B) marker. Not propertizing like
+ ;; this makes the behaviour of these markers consistent whether they are
+ ;; displayed for an already boosted/favourited toot or as the result of
+ ;; the toot having just been favourited/boosted.
(concat (when boosted
- (format
- (propertize "(%s) "
- 'help-echo
- (mastodon-tl--format-faves-count toot))
- (propertize "B" 'face 'mastodon-boost-fave-face)))
+ (mastodon-tl--format-faved-or-boosted-byline "B"))
(when faved
- (format
- (propertize "(%s) "
- 'help-echo
- (mastodon-tl--format-faves-count toot))
- (propertize "F" 'face 'mastodon-boost-fave-face)))
+ (mastodon-tl--format-faved-or-boosted-byline "F")))
+ (propertize
+ (concat
;; we propertize help-echo format faves for author name
;; in `mastodon-tl--byline-author'
(funcall author-byline toot)
@@ -465,6 +513,12 @@ By default it is `mastodon-tl--byline-boosted'"
'boosted-p boosted
'byline t))))
+(defun mastodon-tl--format-faved-or-boosted-byline (letter)
+ "Format the byline marker for a boosted or favorited status.
+LETTER is a string, either F or B."
+ (format "(%s) "
+ (propertize letter 'face 'mastodon-boost-fave-face)))
+
(defun mastodon-tl--render-text (string toot)
"Return a propertized text rendering the given HTML string STRING.
@@ -716,10 +770,9 @@ message is a link which unhides/hides the main body."
(let ((preview-url
(alist-get 'preview_url media-attachement))
(remote-url
- (if (alist-get 'remote_url media-attachement)
- (alist-get 'remote_url media-attachement)
- ;; fallback b/c notifications don't have remote_url
- (alist-get 'url media-attachement)))
+ (or (alist-get 'remote_url media-attachement)
+ ;; fallback b/c notifications don't have remote_url
+ (alist-get 'url media-attachement)))
(type (alist-get 'type media-attachement)))
(if mastodon-tl--display-media-p
(mastodon-media--get-media-link-rendering
@@ -850,6 +903,49 @@ a notification."
(message "You voted for option %s: %s!"
(car option) (cdr option)))))))
+(defun mastodon-tl--find-first-video-in-attachments ()
+ "Return the first media attachment that is a moving image."
+ (let ((attachments (mastodon-tl--property 'attachments))
+ vids)
+ (mapc (lambda (x)
+ (let ((att-type (plist-get x :type)))
+ (when (or (string= "video" att-type)
+ (string= "gifv" att-type))
+ (push x vids))))
+ attachments)
+ (car vids)))
+
+(defun mastodon-tl--mpv-play-video-from-byline ()
+ "Run `mastodon-tl--mpv-play-video-at-point' on first moving image in post."
+ (interactive)
+ (let* ((video (mastodon-tl--find-first-video-in-attachments))
+ (url (plist-get video :url))
+ (type (plist-get video :type)))
+ (mastodon-tl--mpv-play-video-at-point url type)))
+
+(defun mastodon-tl--mpv-play-video-at-point (&optional url type)
+ "Play the video or gif at point with an mpv process.
+URL and TYPE are provided when called while point is on byline,
+in which case play first video or gif from current toot."
+ (interactive)
+ (let ((url (or
+ ;; point in byline:
+ url
+ ;; point in toot:
+ (get-text-property (point) 'image-url)))
+ (type (or ;; in byline:
+ type
+ ;; point in toot:
+ (mastodon-tl--property 'mastodon-media-type))))
+ (if url
+ (if (or (equal type "gifv")
+ (equal type "video"))
+ (progn
+ (message "'q' to kill mpv.")
+ (mpv-start "--loop" url))
+ (message "no moving image here?"))
+ (message "no moving image here?"))))
+
(defun mastodon-tl--toot (toot)
"Formats TOOT and insertes it into the buffer."
(mastodon-tl--insert-status
@@ -1349,7 +1445,7 @@ is a no-op."
;; We need to re-schedule for an earlier time
(cancel-timer mastodon-tl--timestamp-update-timer)
(setq mastodon-tl--timestamp-update-timer
- (run-at-time this-update
+ (run-at-time (time-to-seconds (time-subtract this-update (current-time)))
nil ;; don't repeat
#'mastodon-tl--update-timestamps-callback
(current-buffer) nil)))))))
@@ -1402,7 +1498,9 @@ from the start if it is nil."
(copy-marker previous-timestamp))
;; otherwise we are done for now; schedule a new run for when needed
(setq mastodon-tl--timestamp-update-timer
- (run-at-time mastodon-tl--timestamp-next-update
+ (run-at-time (time-to-seconds
+ (time-subtract mastodon-tl--timestamp-next-update
+ (current-time)))
nil ;; don't repeat
#'mastodon-tl--update-timestamps-callback
buffer nil))))))))
@@ -1452,7 +1550,9 @@ JSON is the data returned from the server."
update-function ,update-function)
mastodon-tl--timestamp-update-timer
(when mastodon-tl--enable-relative-timestamps
- (run-at-time mastodon-tl--timestamp-next-update
+ (run-at-time (time-to-seconds
+ (time-subtract mastodon-tl--timestamp-next-update
+ (current-time)))
nil ;; don't repeat
#'mastodon-tl--update-timestamps-callback
(current-buffer)
@@ -1482,7 +1582,9 @@ Runs synchronously."
,update-function)
mastodon-tl--timestamp-update-timer
(when mastodon-tl--enable-relative-timestamps
- (run-at-time mastodon-tl--timestamp-next-update
+ (run-at-time (time-to-seconds
+ (time-subtract mastodon-tl--timestamp-next-update
+ (current-time)))
nil ;; don't repeat
#'mastodon-tl--update-timestamps-callback
(current-buffer)
diff --git a/lisp/mastodon-toot.el b/lisp/mastodon-toot.el
index b50cbf6..48e7d96 100644
--- a/lisp/mastodon-toot.el
+++ b/lisp/mastodon-toot.el
@@ -70,13 +70,11 @@
(autoload 'mastodon-tl--toot-id "mastodon-tl")
(autoload 'mastodon-toot "mastodon")
-;;;###autoload
(defgroup mastodon-toot nil
"Tooting in Mastodon."
:prefix "mastodon-toot-"
:group 'mastodon)
-;;;###autoload
(defcustom mastodon-toot--default-visibility "public"
"The default visibility for new toots.
@@ -89,19 +87,16 @@ followers-only), or \"direct\"."
(const :tag "followers only" "private")
(const :tag "direct" "direct")))
-;;;###autoload
(defcustom mastodon-toot--default-media-directory "~/"
"The default directory when prompting for a media file to upload."
:group 'mastodon-toot
:type 'string)
-;;;###autoload
(defcustom mastodon-toot--attachment-height 80
"Height of the attached images preview in the toot draft buffer."
:group 'mastodon-toot
:type 'integer)
-;;;###autoload
(defcustom mastodon-toot--enable-completion-for-mentions
(if (require 'company nil :noerror) "following" "off")
"Whether to enable company completion for mentions.
@@ -115,7 +110,6 @@ This is only used if company mode is installed."
(const :tag "following only" "following")
(const :tag "all users" "all")))
-;;;###autoload
(defcustom mastodon-toot--enable-custom-instance-emoji nil
"Whether to enable your instance's custom emoji by default."
:group 'mastodon-toot
@@ -200,7 +194,10 @@ Remove MARKER if REMOVE is non-nil, otherwise add it."
(unless remove
(goto-char bol)
(insert (format "(%s) "
- (propertize marker 'face 'success)))))))
+ (propertize marker 'face 'success)))))
+ ;; leave point after the marker:
+ (unless remove
+ (mastodon-tl--goto-next-toot))))
(defun mastodon-toot--action (action callback)
"Take ACTION on toot at point, then execute CALLBACK.
diff --git a/lisp/mastodon.el b/lisp/mastodon.el
index bd0a557..a52bf41 100644
--- a/lisp/mastodon.el
+++ b/lisp/mastodon.el
@@ -32,6 +32,7 @@
;;; Code:
(require 'cl-lib) ; for `cl-some' call in mastodon
+(require 'mastodon-toot)
(declare-function discover-add-context-menu "discover")
(declare-function emojify-mode "emojify")
@@ -52,10 +53,10 @@
(autoload 'mastodon-profile--get-toot-author "mastodon-profile")
(autoload 'mastodon-profile--make-author-buffer "mastodon-profile")
(autoload 'mastodon-profile--show-user "mastodon-profile")
-(autoload 'mastodon-toot--compose-buffer "mastodon-toot")
-(autoload 'mastodon-toot--reply "mastodon-toot")
-(autoload 'mastodon-toot--toggle-boost "mastodon-toot")
-(autoload 'mastodon-toot--toggle-favourite "mastodon-toot")
+;; (autoload 'mastodon-toot--compose-buffer "mastodon-toot")
+;; (autoload 'mastodon-toot--reply "mastodon-toot")
+;; (autoload 'mastodon-toot--toggle-boost "mastodon-toot")
+;; (autoload 'mastodon-toot--toggle-favourite "mastodon-toot")
(autoload 'mastodon-discover "mastodon-discover")
(autoload 'mastodon-tl--block-user "mastodon-tl")
@@ -70,9 +71,9 @@
(autoload 'mastodon-notifications--follow-request-accept "mastodon-notifications")
(autoload 'mastodon-notifications--follow-request-reject "mastodon-notifications")
(autoload 'mastodon-search--search-query "mastodon-search")
-(autoload 'mastodon-toot--delete-toot "mastodon-toot")
-(autoload 'mastodon-toot--copy-toot-url "mastodon-toot")
-(autoload 'mastodon-toot--pin-toot-toggle "mastodon-toot")
+;; (autoload 'mastodon-toot--delete-toot "mastodon-toot")
+;; (autoload 'mastodon-toot--copy-toot-url "mastodon-toot")
+;; (autoload 'mastodon-toot--pin-toot-toggle "mastodon-toot")
(autoload 'mastodon-auth--get-account-name "mastodon-auth")
;; (autoload 'mastodon-async--stream-federated "mastodon-async")
;; (autoload 'mastodon-async--stream-local "mastodon-async")
@@ -82,11 +83,9 @@
(autoload 'mastodon-profile--update-user-profile-note "mastodon-profile")
(autoload 'mastodon-auth--user-acct "mastodon-auth")
(autoload 'mastodon-tl--poll-vote "mastodon-http")
-(autoload 'mastodon-toot--delete-and-redraft-toot "mastodon-toot")
+;; (autoload 'mastodon-toot--delete-and-redraft-toot "mastodon-toot")
(autoload 'mastodon-profile--view-bookmarks "mastodon-profile")
-(autoload 'mastodon-toot--bookmark-toot-toggle "mastodon-toot")
-(autoload 'mastodon-toot--enable-custom-emoji "mastodon-toot")
-(defvar mastodon-toot--enable-custom-instance-emoji)
+;; (autoload 'mastodon-toot--bookmark-toot-toggle "mastodon-toot")
(defgroup mastodon nil
"Interface with Mastodon."