File: magithub-notification.el

package info (click to toggle)
magithub 0.1.7-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 1,920 kB
  • sloc: lisp: 3,684; makefile: 82
file content (170 lines) | stat: -rw-r--r-- 6,982 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;;; magithub-notification.el --- notification handling  -*- lexical-binding: t; -*-

;; Copyright (C) 2017-2018  Sean Allred

;; Author: Sean Allred <code@seanallred.com>
;; Keywords: lisp

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; View and interact with notifications.

;;; Code:

(require 'thingatpt)

(require 'magithub-issue-view)

(defvar magit-magithub-notification-section-map
  (let ((m (make-sparse-keymap)))
    (set-keymap-parent m magithub-map)
    (define-key m [remap magit-visit-thing] #'magithub-notification-visit)
    (define-key m [remap magithub-browse-thing] #'magithub-notification-browse)
    (define-key m [remap magit-refresh] #'magithub-notification-refresh)
    m))

(defvar magit-magithub-notifications-section-map
  (let ((m (make-sparse-keymap)))
    (set-keymap-parent m magithub-map)
    (define-key m [remap magit-refresh] #'magithub-notification-refresh)
    m))

(defun magithub-notifications (&optional include-read only-participating since before)
  "Get notifications for the currently-authenticated user.
If INCLUDE-READ is non-nil, read notifications are returned as
well.

If ONLY-PARTICIPATING is non-nil, only return notifications that
the user is directly participating in.

If SINCE/BEFORE are non-nil, they are time values.  Only
notifications received since/before this value will be returned.
See also Info node `(elisp)Time of Day'."
  (let (args)
    (when include-read
      (push '(:all "true") args))
    (when only-participating
      (push '(:participating "true") args))
    (when since
      (push `(:since ,(format-time-string "%FT%T%z" since)) args))
    (when before
      (push `(:before ,(format-time-string "%FT%T%z" before)) args))
    (magithub-cache :notification
      `(magithub-request
        (ghubp-unpaginate
         (ghubp-get-notifications ,@(apply #'append args)))))))

(defun magithub-notification-refresh ()
  (interactive)
  (magithub-cache-without-cache :notification
    (magit-refresh))
  (message "(magithub) notifications refreshed"))

(defun magithub-notification-read-p (notification)
  "Non-nil if NOTIFICATION has been read."
  (not (magithub-notification-unread-p notification)))

(defun magithub-notification-unread-p (notification)
  "Non-nil if NOTIFICATION has been not been read."
  (alist-get 'unread notification))

(defconst magithub-notification-reasons
  '(("assign" . "You were assigned to the Issue.")
    ("author" . "You created the thread.")
    ("comment" . "You commented on the thread.")
    ("invitation" . "You accepted an invitation to contribute to the repository.")
    ("manual" . "You subscribed to the thread (via an Issue or Pull Request).")
    ("mention" . "You were specifically @mentioned in the content.")
    ("state_change" . "You changed the thread state (for example, closing an Issue or merging a Pull Request).")
    ("subscribed" . "You're watching the repository.")
    ("team_mention" . "You were on a team that was mentioned."))
  "Human-readable description of possible notification reasons.
Stripped from the GitHub API Docs:

    URL `https://developer.github.com/v3/activity/notifications/#notification-reasons'.")

(defun magithub-notification-reason (notification &optional expanded)
  "Get the reason NOTIFICATION exists.
If EXPANDED is non-nil, use `magithub-notification-reasons' to
get a more verbose explanation."
  (let-alist notification
    (if expanded
        (cdr (assoc-string .reason magithub-notification-reasons
                           "(Unknown)"))
      .reason)))

(defalias 'magithub-notification-visit #'magithub-notification-browse)
(defun magithub-notification-browse (notification)
  "Visits the URL pointed to by NOTIFICATION."
  (interactive (list (thing-at-point 'github-notification)))
  (magithub-request
   (if notification
       (let-alist notification
         (cond
          ((member .subject.type '("Issue" "PullRequest"))
           (ghubp-patch-notifications-threads-id notification)
           (magithub-issue-view (ghubp-follow-get .subject.url)))
          (t (if-let ((url (or .subject.latest_comment_url .subject.url))
                      (html-url (alist-get 'html_url (ghubp-follow-get url))))
                 (browse-url html-url)
               (user-error "No target URL found")))))
     (user-error "No notification here"))))

(defvar magithub-notification-details-hook
  '(magithub-notification-detail-insert-type
    magithub-notification-detail-insert-updated
    magithub-notification-detail-insert-expanded-reason)
  "Detail functions for notification-type sections.
These details appear under notifications as expandable content.

Each function takes the notification object as its only
argument.")

(defun magithub-notification-insert-section (notification)
  "Insert NOTIFICATION as a section into the buffer."
  (let-alist notification
    (magit-insert-section (magithub-notification notification (not .unread))
      (magit-insert-heading
        (format "%-12s %s"
                (propertize (magithub-notification-reason notification)
                            'face 'magithub-notification-reason
                            'help-echo (magithub-notification-reason notification t))
                (propertize (concat .subject.title "\n")
                            'face (if .unread 'highlight))))
      (run-hook-with-args 'magithub-notification-details-hook notification))))

(defun magithub-notification-detail-insert-type (notification)
  "Insert NOTIFICATION's type."
  (let-alist notification
    (insert (format "%-12s %s\n" "Type:"
                    (propertize .subject.type 'face 'magit-dimmed)))))

(defun magithub-notification-detail-insert-updated (notification)
  "Insert a timestamp of when NOTIFICATION was last updated."
  (let-alist notification
    (insert (format "%-12s %s\n" "Updated:"
                    (propertize .updated_at 'face 'magit-dimmed)))))

(defun magithub-notification-detail-insert-expanded-reason (notification)
  "Insert NOTIFICATION's expanded reason.
See also `magithub-notification-reasons'."
  (insert (format "%-12s %s\n" "Reason:"
                  (propertize (or (magithub-notification-reason notification t)
                                  "(no description available)")
                              'face 'magit-dimmed))))

(provide 'magithub-notification)
;;; magithub-notification.el ends here