aboutsummaryrefslogtreecommitdiff
path: root/lisp/mastodon-tl.el
diff options
context:
space:
mode:
authormarty hiatt <martianhiatus@riseup.net>2024-08-02 11:15:14 +0200
committermarty hiatt <martianhiatus@riseup.net>2024-08-02 12:24:20 +0200
commit35a26600afca9bcf6fd033a2a7199a4df048c655 (patch)
treee07bf03c7fb77f0bf4c618434c14f8cbfed3d50b /lisp/mastodon-tl.el
parente66ce7b6fb55a5f78a840ca4c00aa9773bbc9e4f (diff)
reimplement folding via insert body only.
adds a toot-body prop to body only adds toot-foldable and toot-folded props to whole toot (so can check it at byline) shouldn't add any wrong newlines adds no-byline flag to insert-status
Diffstat (limited to 'lisp/mastodon-tl.el')
-rw-r--r--lisp/mastodon-tl.el188
1 files changed, 101 insertions, 87 deletions
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index 797b355..99d6eac 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -1506,7 +1506,8 @@ Runs `mastodon-tl--render-text' and fetches poll or media."
(string= reply-to-id prev-id)))
(defun mastodon-tl--insert-status (toot body author-byline action-byline
- &optional id base-toot detailed-p thread domain unfolded)
+ &optional id base-toot detailed-p
+ thread domain unfolded no-byline)
"Display the content and byline of timeline element TOOT.
BODY will form the section of the toot above the byline.
AUTHOR-BYLINE is an optional function for adding the author
@@ -1523,32 +1524,46 @@ JSON of the toot responded to.
DETAILED-P means display more detailed info. For now
this just means displaying toot client.
THREAD means the status will be displayed in a thread view.
-When DOMAIN, force inclusion of user's domain in their handle."
+When DOMAIN, force inclusion of user's domain in their handle.
+UNFOLDED is a boolean meaning whether to unfold or fold item if foldable.
+NO-BYLINE means just insert toot body, used for folding."
(let* ((start-pos (point))
(reply-to-id (alist-get 'in_reply_to_id toot))
(after-reply-status-p
(when (and thread reply-to-id)
(mastodon-tl--after-reply-status reply-to-id)))
- (type (alist-get 'type toot)))
- ;; body:
+ (type (alist-get 'type toot))
+ (toot-foldable
+ (and mastodon-tl--fold-toots-at-length
+ (length> body mastodon-tl--fold-toots-at-length))))
(insert
(propertize
(concat
- "\n"
- (if (and after-reply-status-p thread)
- (concat (mastodon-tl--symbol 'replied)
- "\n")
- "")
- (let ((bar (mastodon-tl--symbol 'reply-bar))
- (body (mastodon-tl--fold-body-maybe body unfolded)))
+ (propertize
+ (concat
+ "\n"
+ ;; relpy symbol (broken):
(if (and after-reply-status-p thread)
- (propertize body
- 'line-prefix bar
- 'wrap-prefix bar)
- body))
- " \n"
+ (concat (mastodon-tl--symbol 'replied)
+ "\n")
+ "")
+ ;; actual body:
+ (let ((bar (mastodon-tl--symbol 'reply-bar))
+ (body (if (and toot-foldable (not unfolded))
+ (mastodon-tl--fold-body body)
+ body)))
+ (if (and after-reply-status-p thread)
+ (propertize body
+ 'line-prefix bar
+ 'wrap-prefix bar)
+ body)))
+ 'toot-body t) ;; includes newlines etc. for folding
;; byline:
- (mastodon-tl--byline toot author-byline action-byline detailed-p domain))
+ "\n"
+ (if no-byline
+ ""
+ (mastodon-tl--byline toot author-byline action-byline
+ detailed-p domain)))
'item-type 'toot
'item-id (or id ; notification's own id
(alist-get 'id toot)) ; toot id
@@ -1560,90 +1575,86 @@ When DOMAIN, force inclusion of user's domain in their handle."
'item-json toot
'base-toot base-toot
'cursor-face 'mastodon-cursor-highlight-face
- 'notification-type type)
- "\n")
+ 'notification-type type
+ 'toot-foldable toot-foldable
+ 'toot-folded (and toot-foldable (not unfolded)))
+ (if no-byline "" "\n"))
(when mastodon-tl--display-media-p
(mastodon-media--inline-images start-pos (point)))))
-(defun mastodon-tl--fold-body-maybe (body &optional unfolded)
+(defun mastodon-tl--fold-body (body)
"Fold toot BODY if it is very long.
Folding decided by `mastodon-tl--fold-toots-at-length'."
- (if (or unfolded
- (eq nil mastodon-tl--fold-toots-at-length)
- (length< body mastodon-tl--fold-toots-at-length))
- body
- (let* ((heading (mastodon-search--format-heading
- (mastodon-tl--make-link "READ MORE" 'read-more)
- nil :no-newline))
- (display (concat (substring body 0
- mastodon-tl--fold-toots-at-length)
- heading)))
- (propertize display
- 'read-more body))))
+ (let* ((heading (mastodon-search--format-heading
+ (mastodon-tl--make-link "READ MORE" 'read-more)
+ nil :no-newline))
+ (display (concat (substring body 0
+ mastodon-tl--fold-toots-at-length)
+ heading)))
+ (propertize display
+ 'read-more body)))
(defun mastodon-tl--unfold-post (&optional fold)
- "Unfold the toot at point if it is folded (read-more)."
+ "Unfold the toot at point if it is folded (read-more).
+FOLD means to fold it instead"
(interactive)
- ;; if at byline, must search backwards:
- (let* ((byline (mastodon-tl--property 'byline :no-move))
- (read-more-p (mastodon-tl--find-property-range
- 'read-more (point) byline)))
- ;; FIXME: handle any point of the item body and byline
- ;; ie if we are inbetween, try moving up or down (and check again?)
- (if (and (not fold)
- (not read-more-p))
- (user-error "No folded item at point?")
+ (let ((at-byline (mastodon-tl--property 'byline :no-move)))
+ (if (save-excursion
+ (when (not at-byline)
+ (mastodon-tl--goto-next-item))
+ (not (mastodon-tl--property 'toot-foldable :no-move)))
+ (user-error "No foldable item at point?")
(let* ((inhibit-read-only t)
- (range (mastodon-tl--find-property-range 'item-json (point)))
- ;; FIXME: we need to reload toot data if we want
- ;; fave/boost/bookmark stats to display correctly. ie if we do
- ;; an action then (un)fold, stats/(*)/etc display incorrectly.
-
- ;; another option may be to check favourited-p/boosted-p prop,
- ;; and then call toot--action-success again with the relevant
- ;; symbol (to insert it after re-display)? as per
- ;; `mastodon-toot--toggle-boost-or-favourite' callback?
-
- ;; or, is it simpler to just not replace the byline? to do that,
- ;; we need to call `mastodont-tl--insert-status' without
- ;; inserting a byline, so that props are all correct...
- (toot (mastodon-tl--property 'item-json)))
- ;; `replace-region-contents' is much too slow, our hack from fedi.el
- ;; is much simpler and much faster:
- (let ((beg (car range))
- (end (cdr range))
- (last-point (point)))
- (save-excursion
- (goto-char beg)
- (delete-region beg end)
- (delete-char 1) ;; prevent newlines accumulating
- (mastodon-tl--toot toot nil nil nil
- (when (not fold) :unfolded)))
- (cond ((or byline
- (and fold
- ;; if point was in area now folded:
- (> last-point
- (+ beg mastodon-tl--fold-toots-at-length))))
- (mastodon-tl--goto-next-item))
- (t
- (goto-char last-point)
- (beginning-of-line))))))))
+ (body-range (mastodon-tl--find-property-range 'toot-body
+ (point) :backward))
+ (toot (mastodon-tl--property 'item-json :no-move))
+ ;; `replace-region-contents' is much too slow, our hack from
+ ;; fedi.el is much simpler and much faster:
+ (beg (car body-range))
+ (end (cdr body-range))
+ (last-point (point))
+ (point-after-fold (> last-point
+ (+ beg mastodon-tl--fold-toots-at-length))))
+ ;; save-excursion here useless actually:
+
+ ;; FIXME: because point goes to top of item, the screen gets scrolled
+ ;; by insertion
+ (goto-char beg)
+ (delete-region beg end)
+ (delete-char 1) ;; prevent newlines accumulating
+ ;; insert toot body:
+ (mastodon-tl--toot toot nil nil nil
+ (not fold) ;; (if fold :folded :unfolded)
+ :no-byline)
+ ;; set toot-folded prop on entire toot (not just body):
+ (let ((toot-range ;; post fold action range:
+ (mastodon-tl--find-property-range 'item-json
+ (point) :backward)))
+ (add-text-properties (car toot-range)
+ (cdr toot-range)
+ `(toot-folded ,fold)))
+ ;; try to leave point somewhere sane:
+ (cond ((or at-byline
+ (and fold
+ point-after-fold)) ;; point was in area now folded
+ (ignore-errors (forward-line -1)) ;; in case we are btw
+ (mastodon-tl--goto-next-item)) ;; goto byline
+ (t
+ (goto-char last-point)
+ (when point-after-fold ;; point was in READ MORE heading:
+ (beginning-of-line))))
+ (message (format "%s" (if fold "Fold" "Unfold")))))))
(defun mastodon-tl--fold-post ()
"Fold post at point, if it is too long."
(interactive)
- (mastodon-tl--unfold-post :fold))
+ (mastodon-tl--unfold-post t))
(defun mastodon-tl--fold-post-toggle ()
"Toggle the folding status of the toot at point."
(interactive)
- (let* ((byline-p (mastodon-tl--property 'byline))
- (read-more-p (save-excursion
- (when byline-p
- (previous-line)
- (beginning-of-line))
- (mastodon-tl--property 'read-more))))
- (mastodon-tl--unfold-post (if (not read-more-p) :fold))))
+ (let* ((folded (mastodon-tl--property 'toot-folded :no-move)))
+ (mastodon-tl--unfold-post (not folded))))
;; from mastodon-alt.el:
(defun mastodon-tl--toot-for-stats (&optional toot)
@@ -1705,19 +1716,22 @@ To disable showing the stats, customize
(and (null (mastodon-tl--field 'in_reply_to_id toot))
(not (mastodon-tl--field 'rebloged toot))))
-(defun mastodon-tl--toot (toot &optional detailed-p thread domain unfolded)
+(defun mastodon-tl--toot (toot &optional detailed-p thread domain
+ unfolded no-byline)
"Format TOOT and insert it into the buffer.
DETAILED-P means display more detailed info. For now
this just means displaying toot client.
THREAD means the status will be displayed in a thread view.
-When DOMAIN, force inclusion of user's domain in their handle."
+When DOMAIN, force inclusion of user's domain in their handle.
+UNFOLDED is a boolean meaning whether to unfold or fold item if foldable.
+NO-BYLINE means just insert toot body, used for folding."
(mastodon-tl--insert-status
toot
(mastodon-tl--clean-tabs-and-nl (if (mastodon-tl--has-spoiler toot)
(mastodon-tl--spoiler toot)
(mastodon-tl--content toot)))
'mastodon-tl--byline-author 'mastodon-tl--byline-boosted
- nil nil detailed-p thread domain unfolded))
+ nil nil detailed-p thread domain unfolded no-byline))
(defun mastodon-tl--timeline (toots &optional thread domain)
"Display each toot in TOOTS.