diff options
author | marty hiatt <martianhiatus@riseup.net> | 2024-03-27 14:53:04 +0100 |
---|---|---|
committer | marty hiatt <martianhiatus@riseup.net> | 2024-03-27 14:53:04 +0100 |
commit | d54aa9aa3e4276b9519ff9123e9dc0c123d9dd3b (patch) | |
tree | 6c1e17c1483d41e555160c4acb8505ec7b5d4ecb | |
parent | 90aeac60805ed49da29781b979b6ab3edab671aa (diff) | |
parent | 1454c2253d507adf9be1d413172e0b11b853c661 (diff) |
Merge branch 'develop'
-rw-r--r-- | lisp/mastodon-http.el | 21 | ||||
-rw-r--r-- | lisp/mastodon-media.el | 52 | ||||
-rw-r--r-- | lisp/mastodon-notifications.el | 9 | ||||
-rw-r--r-- | lisp/mastodon-profile.el | 6 | ||||
-rw-r--r-- | lisp/mastodon-tl.el | 17 | ||||
-rw-r--r-- | lisp/mastodon-toot.el | 65 | ||||
-rw-r--r-- | lisp/mastodon-views.el | 2 | ||||
-rw-r--r-- | lisp/mastodon.el | 12 |
8 files changed, 99 insertions, 85 deletions
diff --git a/lisp/mastodon-http.el b/lisp/mastodon-http.el index aef8975..49c94a4 100644 --- a/lisp/mastodon-http.el +++ b/lisp/mastodon-http.el @@ -338,18 +338,27 @@ The upload is asynchronous. On succeeding, item uploaded, and `mastodon-toot--update-status-fields' is run." (let* ((file (file-name-nondirectory filename)) (request-backend 'curl) + (desc `(("description" . ,caption))) (cb (cl-function (lambda (&key data &allow-other-keys) (when data - (push (alist-get 'id data) - mastodon-toot--media-attachment-ids) ; add ID to list - (message (alist-get 'id data)) - (message "Uploading %s... (done)" file) - (mastodon-toot--update-status-fields)))))) + (let* ((id (alist-get 'id data))) + ;; update ids: + (push id mastodon-toot--media-attachment-ids) + ;; pleroma, PUT the description: + ;; this is how the mangane akkoma web client does it + ;; and it seems easier than the other options! + (when (and caption + (not (equal caption (alist-get 'description data)))) + (let ((url (mastodon-http--api (format "media/%s" id)))) + ;; (message "PUTting image description") + (mastodon-http--put url desc))) + (message "Uploading %s... (done)" file) + (mastodon-toot--update-status-fields))))))) (request url :type "POST" - :params `(("description" . ,caption)) + :params desc :files `(("file" . (,file :file ,filename :mime-type "multipart/form-data"))) :parser 'json-read diff --git a/lisp/mastodon-media.el b/lisp/mastodon-media.el index ff40633..bc902aa 100644 --- a/lisp/mastodon-media.el +++ b/lisp/mastodon-media.el @@ -34,6 +34,7 @@ ;;; Code: (require 'url-cache) +(require 'mm-decode) (autoload 'mastodon-tl--propertize-img-str-or-url "mastodon-tl") @@ -177,44 +178,33 @@ with the image." (set-marker marker nil))) (kill-buffer url-buffer)))))) -(defun mastodon-media--process-full-sized-image-response - (status-plist image-options url) +(defun mastodon-media--process-full-sized-image-response (status-plist url) ;; FIXME: refactor this with but not into ;; `mastodon-media--process-image-response'. "Callback function processing the `url-retrieve' response for URL. URL is a full-sized image URL attached to a timeline image. -STATUS-PLIST is a plist of status events as per `url-retrieve'. -IMAGE-OPTIONS are the precomputed options to apply to the image." - (let ((url-buffer (current-buffer)) - (is-error-response-p (eq :error (car status-plist)))) - (let* ((data (unless is-error-response-p - (goto-char (point-min)) - (search-forward "\n\n") - (buffer-substring (point) (point-max)))) - (image (when data - (apply #'create-image data - (if (version< emacs-version "27.1") - (when image-options 'imagemagick) - nil) ; inbuilt scaling in 27.1 - t nil)))) - (when mastodon-media--enable-image-caching - (unless (url-is-cached url) ;; cache if not already cached - (url-store-in-cache url-buffer))) +STATUS-PLIST is a plist of status events as per `url-retrieve'." + (if-let (error-response (plist-get status-plist :error)) + (message "error in loading image: %S" error-response) + (when mastodon-media--enable-image-caching + (unless (url-is-cached url) ;; cache if not already cached + (url-store-in-cache))) + ;; thanks to rahguzar for this idea: + ;; https://codeberg.org/martianh/mastodon.el/issues/540 + (let* ((handle (mm-dissect-buffer t)) + (image (mm-get-image handle)) + (str (image-property image :data))) + ;; (setf (image-property image :max-width) + ;; (window-pixel-width)) (with-current-buffer (get-buffer-create "*masto-image*") (let ((inhibit-read-only t)) (erase-buffer) - (insert " ") - (when image - (add-text-properties (point-min) (point-max) - `( display ,image - keymap ,(if (boundp 'shr-image-map) - shr-image-map - shr-map) - image-url ,url - shr-url ,url)) - (image-mode) - (goto-char (point-min)) - (switch-to-buffer-other-window (current-buffer)))))))) + (insert-image image str) + (special-mode) ; prevent image-mode loop bug + (image-mode) + (goto-char (point-min)) + (switch-to-buffer-other-window (current-buffer)) + (image-transform-fit-both)))))) (defun mastodon-media--load-image-from-url (url media-type start region-length) "Take a URL and MEDIA-TYPE and load the image asynchronously. diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el index f7276d6..0e367c9 100644 --- a/lisp/mastodon-notifications.el +++ b/lisp/mastodon-notifications.el @@ -177,10 +177,11 @@ Status notifications are given when (switch-to-buffer (current-buffer)) (insert str) (goto-char (point-min)) - (while (setq prop (text-property-search-forward 'face 'shr-text t)) - (add-text-properties (prop-match-beginning prop) - (prop-match-end prop) - '(face (font-lock-comment-face shr-text)))) + (let (prop) + (while (setq prop (text-property-search-forward 'face 'shr-text t)) + (add-text-properties (prop-match-beginning prop) + (prop-match-end prop) + '(face (font-lock-comment-face shr-text))))) (buffer-string))) (defun mastodon-notifications--format-note (note type) diff --git a/lisp/mastodon-profile.el b/lisp/mastodon-profile.el index 5929f1c..7b5a700 100644 --- a/lisp/mastodon-profile.el +++ b/lisp/mastodon-profile.el @@ -131,7 +131,7 @@ is updated on entering mastodon mode and on toggle any setting it contains") (define-minor-mode mastodon-profile-update-mode - "Minor mode to update Mastodon user profile." + "Minor mode to update user profile." :group 'mastodon-profile :keymap mastodon-profile-update-mode-map :global nil) @@ -524,7 +524,7 @@ FIELDS means provide a fields vector fetched by other means." (defun mastodon-profile--fields-insert (fields) "Format and insert field pairs (a.k.a profile metadata) in FIELDS." (let* ((car-fields (mapcar #'car fields)) - (left-width (cl-reduce #'max (mapcar #'length car-fields)))) + (left-width (apply #'max (mapcar #'length car-fields)))) (mapconcat (lambda (field) (mastodon-tl--render-text (concat @@ -790,7 +790,7 @@ If the handle does not match a search return then retun NIL." (elt matching-account 0)))) (defun mastodon-profile--account-from-id (user-id) - "Request an account object relating to a USER-ID from Mastodon." + "Request an account object relating to a USER-ID." (mastodon-http--get-json (mastodon-http--api (format "accounts/%s" user-id)))) diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el index 4034ebf..4c0375d 100644 --- a/lisp/mastodon-tl.el +++ b/lisp/mastodon-tl.el @@ -216,7 +216,7 @@ respects the user's `browse-url' settings." ;;; VARIABLES (defvar-local mastodon-tl--buffer-spec nil - "A unique identifier and functions for each Mastodon buffer.") + "A unique identifier and functions for each mastodon buffer.") (defvar-local mastodon-tl--update-point nil "When updating a mastodon buffer this is where new toots will be inserted. @@ -1149,11 +1149,10 @@ SENSITIVE is a flag from the item's JSON data." (goto-char (point-min)) (zlib-decompress-region (goto-char (search-forward "\n\n")) (point-max)) - (mastodon-media--process-full-sized-image-response - nil nil url)) + (mastodon-media--process-full-sized-image-response nil url)) ;; else fetch and load: (url-retrieve url #'mastodon-media--process-full-sized-image-response - (list nil url))))))) + `(,url))))))) ;; POLLS @@ -1366,7 +1365,11 @@ in which case play first video or gif from current toot." (if (mastodon-tl--media-video-p type) (progn (message "'q' to kill mpv.") - (mpv-start "--loop" url)) + (condition-case x + (mpv-start "--loop" url) + (void-function + (message "Looks like mpv.el not installed. Error: %s" + (error-message-string x))))) (message "no moving image here?")) (message "no moving image here?")))) @@ -1716,7 +1719,9 @@ call this function after it is set or use something else." ((mastodon-tl--endpoint-str-= "instance") 'instance-description) ((string= "*mastodon-toot-edits*" buffer-name) - 'toot-edits)))) + 'toot-edits) + ((string= "*masto-image*" (buffer-name)) + 'mastodon-image)))) (defun mastodon-tl--buffer-type-eq (type) "Return t if current buffer type is equal to symbol TYPE." diff --git a/lisp/mastodon-toot.el b/lisp/mastodon-toot.el index 82ad03b..a48d5d9 100644 --- a/lisp/mastodon-toot.el +++ b/lisp/mastodon-toot.el @@ -549,16 +549,18 @@ base toot." "Translate text of toot at point. Uses `lingva.el'." (interactive) - (if (not (require 'lingva nil :no-error)) - (message "Looks like you need to install lingva.el first.") - (if mastodon-tl--buffer-spec - (if-let ((toot (mastodon-tl--property 'item-json))) - (lingva-translate nil - (mastodon-tl--content toot) - (when mastodon-tl--enable-proportional-fonts - t)) - (message "No toot to translate?")) - (message "No mastodon buffer?")))) + (if mastodon-tl--buffer-spec + (if-let ((toot (mastodon-tl--property 'item-json))) + (condition-case x + (lingva-translate nil + (mastodon-tl--content toot) + (when mastodon-tl--enable-proportional-fonts + t)) + (void-function + (message "Looks like you need to install lingva.el. Error: %s" + (error-message-string x)))) + (message "No toot to translate?")) + (message "No mastodon buffer?"))) (defun mastodon-toot--own-toot-p (toot) "Check if TOOT is user's own, for deleting, editing, or pinning it." @@ -697,7 +699,7 @@ CANCEL means the toot was not sent, so we save the toot text as a draft." (mastodon-toot--restore-previous-window-config prev-window-config))) (defun mastodon-toot--cancel () - "Kill new-toot buffer/window. Does not POST content to Mastodon. + "Kill new-toot buffer/window. Does not POST content. If toot is not empty, prompt to save text as a draft." (interactive) (if (mastodon-toot--empty-p) @@ -838,7 +840,7 @@ to `emojify-user-emojis', and the emoji data is updated." ;;; SEND TOOT FUNCTION (defun mastodon-toot--send () - "POST contents of new-toot buffer to Mastodon instance and kill buffer. + "POST contents of new-toot buffer to fediverse instance and kill buffer. If media items have been attached and uploaded with `mastodon-toot--attach-media', they are attached to the toot. If `mastodon-toot--edit-item-id' is non-nil, PUT contents to @@ -1374,7 +1376,7 @@ LENGTH is the maximum character length allowed for a poll option." collect (read-string (format "Poll option [%s/%s] [max %s chars]: " x count length)))) - (longest (cl-reduce #'max (mapcar #'length choices)))) + (longest (apply #'max (mapcar #'length choices)))) (if (> longest length) (progn (message "looks like you went over the max length. Try again.") @@ -1843,7 +1845,15 @@ a draft into the buffer. EDIT means we are editing an existing toot, not composing a new one." (let* ((buffer-name (if edit "*edit toot*" "*new toot*")) (buffer-exists (get-buffer buffer-name)) - (buffer (or buffer-exists (get-buffer-create buffer-name))) + (buffer (if (not buffer-exists) + (get-buffer-create buffer-name) + ;; if a user hits reply while a compose buffer is already + ;; open, we really ought to wipe it all and start over. + (switch-to-buffer-other-window buffer-exists) + (if (not (y-or-n-p "Overwrite existing compose buffer?")) + (user-error "Aborting") + (kill-buffer-and-window) + (get-buffer-create buffer-name)))) (inhibit-read-only t) (reply-text (alist-get 'content (or (alist-get 'reblog reply-json) @@ -1858,19 +1868,18 @@ EDIT means we are editing an existing toot, not composing a new one." ;; use toot visibility setting from the server: (mastodon-profile--get-source-pref 'privacy) "public")) ; fallback - (unless buffer-exists - (if mastodon-toot-display-orig-in-reply-buffer - (progn - (mastodon-toot--display-docs-and-status-fields reply-text) - (mastodon-toot--fill-reply-in-compose)) - (mastodon-toot--display-docs-and-status-fields)) - ;; `reply-to-user' (alone) is also used by `mastodon-tl--dm-user', so - ;; perhaps we should not always call --setup-as-reply, or make its - ;; workings conditional on reply-to-id. currently it only checks for - ;; reply-to-user. - (mastodon-toot--setup-as-reply reply-to-user reply-to-id reply-json - ;; only initial-text if reply (not edit): - (when reply-json initial-text))) + (if mastodon-toot-display-orig-in-reply-buffer + (progn + (mastodon-toot--display-docs-and-status-fields reply-text) + (mastodon-toot--fill-reply-in-compose)) + (mastodon-toot--display-docs-and-status-fields)) + ;; `reply-to-user' (alone) is also used by `mastodon-tl--dm-user', so + ;; perhaps we should not always call --setup-as-reply, or make its + ;; workings conditional on reply-to-id. currently it only checks for + ;; reply-to-user. + (mastodon-toot--setup-as-reply reply-to-user reply-to-id reply-json + ;; only initial-text if reply (not edit): + (when reply-json initial-text)) (unless mastodon-toot--max-toot-chars ;; no need to fetch from `mastodon-profile-account-settings' as ;; `mastodon-toot--max-toot-chars' is set when we set it @@ -1944,7 +1953,7 @@ Only text that is not one of these faces will be spell-checked." (define-minor-mode mastodon-toot-mode - "Minor mode to capture Mastodon toots." + "Minor mode for composing toots." :keymap mastodon-toot-mode-map :global nil) diff --git a/lisp/mastodon-views.el b/lisp/mastodon-views.el index d0f310b..e9e89c0 100644 --- a/lisp/mastodon-views.el +++ b/lisp/mastodon-views.el @@ -852,7 +852,7 @@ MISSKEY means the instance is a Misskey or derived server." IND is the optional indentation level to print at." (let* ((cars (mapcar (lambda (x) (symbol-name (car x))) response)) - (pad (1+ (cl-reduce #'max (mapcar #'length cars))))) + (pad (1+ (apply #'max (mapcar #'length cars))))) (while response (let ((el (pop response))) (cond diff --git a/lisp/mastodon.el b/lisp/mastodon.el index 4667450..70ab73c 100644 --- a/lisp/mastodon.el +++ b/lisp/mastodon.el @@ -110,8 +110,8 @@ :group 'external) (defcustom mastodon-instance-url "https://mastodon.social" - "Base URL for the Mastodon instance you want to be active. -For example, if your mastodon username is + "Base URL for the fediverse instance you want to be active. +For example, if your username is \"example_user@social.instance.org\", and you want this account to be active, the value of this variable should be \"https://social.instance.org\". @@ -125,7 +125,7 @@ changes to take effect." (defcustom mastodon-active-user nil "Username of the active user. -For example, if your mastodon username is +For example, if your username is \"example_user@social.instance.org\", and you want this account to be active, the value of this variable should be \"example_user\". @@ -275,7 +275,7 @@ See `mastodon-toot-display-orig-in-reply-buffer'.") ;;;###autoload (defun mastodon () - "Connect Mastodon client to `mastodon-instance-url' instance." + "Connect client to `mastodon-instance-url' instance." (interactive) (let* ((tls (list "home" "local" @@ -295,7 +295,7 @@ See `mastodon-toot-display-orig-in-reply-buffer'.") (if buffer (pop-to-buffer buffer '(display-buffer-same-window)) (mastodon-tl--get-home-timeline) - (message "Loading Mastodon account %s on %s..." + (message "Loading fediverse account %s on %s..." (mastodon-auth--user-acct) mastodon-instance-url)))) @@ -477,7 +477,7 @@ Calls `mastodon-tl--get-buffer-type', which see." (add-hook 'mastodon-mode-hook #'mastodon-mode-hook-fun) (define-derived-mode mastodon-mode special-mode "Mastodon" - "Major mode for Mastodon, the federated microblogging network." + "Major mode for fediverse services using the Mastodon API." (read-only-mode 1)) (provide 'mastodon) |