aboutsummaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authormarty hiatt <martianhiatus@riseup.net>2024-10-11 09:26:57 +0200
committermarty hiatt <martianhiatus@riseup.net>2024-10-11 09:26:57 +0200
commit64fa8d9066b3a58895e595fc3ca44249edada5df (patch)
tree0202af089f6d45403fe7d520312fe87994236dbb /lisp
parentf3af53067b7cd7827ccf133e5e729aeed72ce807 (diff)
working v rough grouped notifs
Diffstat (limited to 'lisp')
-rw-r--r--lisp/mastodon-notifications.el245
-rw-r--r--lisp/mastodon-tl.el28
2 files changed, 153 insertions, 120 deletions
diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el
index 46f2423..a2c0453 100644
--- a/lisp/mastodon-notifications.el
+++ b/lisp/mastodon-notifications.el
@@ -204,123 +204,150 @@ JSON is a list of alists."
for x in ids
collect (mastodon-notifications--alist-by-value x 'id json)))
-(defun mastodon-notifications--format-note (group json type)
- "Format for a NOTE of TYPE."
+(defun mastodon-notifications--format-note (group status accounts)
+ "Format for a GROUP notification.
+JSON is the full notifications JSON."
;; FIXME: apply/refactor filtering as per/with `mastodon-tl--toot'
- ;; (if (member type mastodon-notifications-grouped-types)
(let-alist group
;; .sample_account_ids .status_id .notifications_count
;; .most_recent_notifiation_id
- (let* ((status (mastodon-notifications--alist-by-value
- .status_id 'id (alist-get 'statuses json)))
- (accounts (mastodon-notifications--group-accounts
- .sample_account_ids (alist-get 'accounts json))))
- (insert (symbol-name type) "\n"
- "accounts: " (mapconcat 'identity .sample_account_ids ", ") "\n"
- (if (not (> .notifications_count (length .sample_account_ids)))
- ""
- (concat
- "and"
- (number-to-string
- (- .notifications_count
- (length .sample_account_ids))))
- "others \n")
- ;; "count: " (number-to-string .notifications_count)
- (alist-get type mastodon-notifications--action-alist)
- "\n toot: " (or .status_id "") "\n"
- "\n\n"))
- ))
-
-;; non-grouped notifs:
-;; (let* ((id (alist-get 'id note))
-;; (profile-note
-;; (when (eq 'follow-request type)
-;; (let ((str (mastodon-tl--field
-;; 'note
-;; (mastodon-tl--field 'account note))))
-;; (if mastodon-notifications--profile-note-in-foll-reqs-max-length
-;; (string-limit str mastodon-notifications--profile-note-in-foll-reqs-max-length)
-;; str))))
-;; (status (mastodon-tl--field 'status note))
-;; (follower (alist-get 'username (alist-get 'account note)))
-;; (toot (alist-get 'status note))
-;; (filtered (mastodon-tl--field 'filtered toot))
-;; (filters (when filtered
-;; (mastodon-tl--current-filters filtered))))
-;; (if (and filtered (assoc "hide" filters))
-;; nil
-;; (mastodon-tl--insert-status
-;; ;; toot
-;; (cond ((or (eq type 'follow)
-;; (eq type 'follow-request))
-;; ;; Using reblog with an empty id will mark this as something
-;; ;; non-boostable/non-favable.
-;; (cons '(reblog (id . nil)) note))
-;; ;; reblogs/faves use 'note' to process their own json
-;; ;; not the toot's. this ensures following etc. work on such notifs
-;; ((or (eq type 'favourite)
-;; (eq type 'boost))
-;; note)
-;; (t
-;; status))
-;; ;; body
-;; (let ((body (if-let ((match (assoc "warn" filters)))
-;; (mastodon-tl--spoiler toot (cadr match))
-;; (mastodon-tl--clean-tabs-and-nl
-;; (if (mastodon-tl--has-spoiler status)
-;; (mastodon-tl--spoiler status)
-;; (if (eq 'follow-request type)
-;; (mastodon-tl--render-text profile-note)
-;; (mastodon-tl--content status)))))))
-;; (cond ((or (eq type 'follow)
-;; (eq type 'follow-request))
-;; (if (eq type 'follow)
-;; (propertize "Congratulations, you have a new follower!"
-;; 'face 'default)
-;; (concat
-;; (propertize
-;; (format "You have a follow request from... %s"
-;; follower)
-;; 'face 'default)
-;; (when mastodon-notifications--profile-note-in-foll-reqs
-;; (concat
-;; ":\n"
-;; (mastodon-notifications--comment-note-text body))))))
-;; ((or (eq type 'favourite)
-;; (eq type 'boost))
-;; (mastodon-notifications--comment-note-text body))
-;; (t body)))
-;; ;; author-byline
-;; (if (or (eq type 'follow)
-;; (eq type 'follow-request)
-;; (eq type 'mention))
-;; 'mastodon-tl--byline-author
-;; (lambda (_status &rest _args) ; unbreak stuff
-;; (mastodon-tl--byline-author note)))
-;; ;; action-byline
-;; (lambda (_status)
-;; (mastodon-notifications--byline-concat
-;; (alist-get type mastodon-notifications--action-alist)
-;; ))
-;; id
-;; ;; base toot
-;; (when (or (eq type 'favourite)
-;; (eq type 'boost))
-;; status))))))
+ (let* ((type .type)
+ (type-sym (intern .type))
+ (profile-note
+ (when (eq type-sym 'follow-request)
+ (let ((str (mastodon-tl--field
+ 'note
+ (car accounts))))
+ (if mastodon-notifications--profile-note-in-foll-reqs-max-length
+ (string-limit str mastodon-notifications--profile-note-in-foll-reqs-max-length)
+ str))))
+ (follower (car .sample_account_ids))
+ (filtered (mastodon-tl--field 'filtered status)) ;;toot))
+ (filters (when filtered
+ (mastodon-tl--current-filters filtered))))
+ (if (and filtered (assoc "hide" filters))
+ nil
+ (mastodon-tl--insert-status
+ ;; toot
+ (if (member type-sym '(follow follow_request))
+ ;; Using reblog with an empty id will mark this as something
+ ;; non-boostable/non-favable.
+ (cons '(reblog (id . nil)) status) ;;note))
+ ;; reblogs/faves use 'note' to process their own json not the
+ ;; toot's. this ensures following etc. work on such notifs
+ status) ;; FIXME: fix following on these notifs
+ ;; body
+ (let ((body (if-let ((match (assoc "warn" filters)))
+ (mastodon-tl--spoiler toot (cadr match))
+ (mastodon-tl--clean-tabs-and-nl
+ (if (mastodon-tl--has-spoiler status)
+ (mastodon-tl--spoiler status)
+ (if (eq type 'follow-request)
+ (mastodon-tl--render-text profile-note)
+ (mastodon-tl--content status)))))))
+ (cond ((eq type-sym 'follow)
+ (propertize "Congratulations, you have a new follower!"
+ 'face 'default))
+ ((eq type-sym 'follow-request)
+ (concat
+ (propertize
+ (format "You have a follow request from... %s"
+ follower)
+ 'face 'default)
+ (when mastodon-notifications--profile-note-in-foll-reqs
+ (concat
+ ":\n"
+ (mastodon-notifications--comment-note-text body)))))
+ ((member type-sym '(favourite boost))
+ (mastodon-notifications--comment-note-text body))
+ (t body)))
+ ;; author-byline
+ (lambda (&rest _args)
+ (mastodon-notifications--byline-account accounts status))
+ ;; action-byline
+ (lambda (_status)
+ (mastodon-notifications--byline-concat
+ (alist-get type-sym mastodon-notifications--action-alist)))
+ .status_id
+ ;; base toot
+ (when (member type-sym '(favourite boost))
+ status)
+ nil nil nil nil
+ nil group))))) ;; insert status still needs our group data
+
+;; FIXME: REFACTOR with -tl--byline:
+;; we provide account directly, rather than let-alisting toot
+;; almost everything is .account.field anyway
+;; but toot still needed also, for attachments, etc.
+(defun mastodon-notifications--byline-account
+ (accounts toot &optional avatar domain)
+ "Propertize author byline ACCOUNT for TOOT, the item responded to.
+With arg AVATAR, include the account's avatar image.
+When DOMAIN, force inclusion of user's domain in their handle."
+ (cl-loop
+ for account in accounts
+ concat
+ (let-alist account
+ (concat
+ ;; avatar insertion moved up to `mastodon-tl--byline' by default to
+ ;; be outside 'byline propt.
+ (when (and avatar ; used by `mastodon-profile--format-user'
+ mastodon-tl--show-avatars
+ mastodon-tl--display-media-p
+ (mastodon-tl--image-trans-check))
+ (mastodon-media--get-avatar-rendering .avatar))
+ ;; username:
+ (propertize (if (not (string-empty-p .display_name))
+ .display_name
+ .username)
+ '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
+ ;; but don't add it to "following"/"follows" on profile views:
+ ;; we don't have a tl--buffer-spec yet:
+ (unless (or (string-suffix-p "-followers*" (buffer-name))
+ (string-suffix-p "-following*" (buffer-name)))
+ (mastodon-tl--format-byline-help-echo toot)))
+ ;; handle:
+ " ("
+ (propertize (concat "@" .acct
+ (when domain
+ (concat "@"
+ (url-host
+ (url-generic-parse-url .url)))))
+ 'face 'mastodon-handle-face
+ 'mouse-face 'highlight
+ 'mastodon-tab-stop 'user-handle
+ 'account account
+ 'shr-url .url
+ 'keymap mastodon-tl--link-keymap
+ 'mastodon-handle (concat "@" .acct)
+ 'help-echo (concat "Browse user profile of @" .acct))
+ ")"
+ (if (< 1 (length accounts)) "\n" "")))))
(defun mastodon-notifications--by-type (groups json)
"Filter NOTE for those listed in `mastodon-notifications--types-alist'.
Call its function in that list on NOTE."
- (cl-loop for g in groups
- for type = (alist-get 'type g)
- for fun = (cdr (assoc type mastodon-notifications--types-alist))
- for start-pos = (point)
- do (when fun
- (funcall fun g json)
- (when mastodon-tl--display-media-p
- ;; images-in-notifs custom is handeld in
- ;; `mastodon-tl--media-attachment', not here
- (mastodon-media--inline-images start-pos (point))))))
+ (setq masto-grouped-notifs json)
+ (cl-loop
+ for g in groups
+ for start-pos = (point)
+ for accounts = (mastodon-notifications--group-accounts
+ (alist-get 'sample_account_ids g)
+ (alist-get 'accounts json))
+ for status = (mastodon-notifications--alist-by-value
+ (alist-get 'status_id g) 'id
+ (alist-get 'statuses json))
+ do (mastodon-notifications--format-note g status accounts)
+ (when mastodon-tl--display-media-p
+ ;; images-in-notifs custom is handeld in
+ ;; `mastodon-tl--media-attachment', not here
+ (mastodon-media--inline-images start-pos (point)))))
(defun mastodon-notifications--timeline (json)
"Format JSON in Emacs buffer."
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index 2e0588f..f611c89 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -711,7 +711,8 @@ LETTER is a string, F for favourited, B for boosted, or K for bookmarked."
(image-transforms-p)))
(defun mastodon-tl--byline (toot author-byline action-byline
- &optional detailed-p domain base-toot)
+ &optional detailed-p domain base-toot
+ group)
"Generate byline for TOOT.
AUTHOR-BYLINE is a function for adding the author portion of
the byline that takes one variable.
@@ -723,13 +724,15 @@ this just means displaying toot client.
When DOMAIN, force inclusion of user's domain in their handle.
BASE-TOOT is JSON for the base toot, if any."
(let* ((created-time
- ;; bosts and faves in notifs view
- ;; (makes timestamps be for the original toot not the boost/fave):
- (or (mastodon-tl--field 'created_at
- (mastodon-tl--field 'status toot))
- ;; all other toots, inc. boosts/faves in timelines:
- ;; (mastodon-tl--field auto fetches from reblogs if needed):
- (mastodon-tl--field 'created_at toot)))
+ (if group
+ (mastodon-tl--field 'latest_page_notification_at group)
+ ;; bosts and faves in notifs view
+ ;; (makes timestamps be for the original toot not the boost/fave):
+ (or (mastodon-tl--field 'created_at
+ (mastodon-tl--field 'status toot))
+ ;; all other toots, inc. boosts/faves in timelines:
+ ;; (mastodon-tl--field auto fetches from reblogs if needed):
+ (mastodon-tl--field 'created_at toot))))
(parsed-time (date-to-time created-time))
(faved (eq t (mastodon-tl--field 'favourited toot)))
(boosted (eq t (mastodon-tl--field 'reblogged toot)))
@@ -1519,7 +1522,7 @@ Runs `mastodon-tl--render-text' and fetches poll or media."
(defun mastodon-tl--insert-status
(toot body author-byline action-byline &optional id base-toot
- detailed-p thread domain unfolded no-byline)
+ detailed-p thread domain unfolded no-byline group)
"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
@@ -1539,7 +1542,10 @@ THREAD means the status will be displayed in a thread view.
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* ((reply-to-id (alist-get 'in_reply_to_id toot))
+ (let* ((reply-to-id
+ (if group
+ (alist-get 'status_id group)
+ (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)))
@@ -1572,7 +1578,7 @@ NO-BYLINE means just insert toot body, used for folding."
"\n"
(unless no-byline
(mastodon-tl--byline toot author-byline action-byline
- detailed-p domain base-toot)))
+ detailed-p domain base-toot group)))
'item-type 'toot
'item-id (or id ; notification's own id
(alist-get 'id toot)) ; toot id