Monorepo for Tangled
tangled.org
1package models
2
3import (
4 "context"
5 "fmt"
6 "time"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 "tangled.org/core/idresolver"
10)
11
12type NotificationType string
13
14const (
15 NotificationTypeRepoStarred NotificationType = "repo_starred"
16 NotificationTypeIssueCreated NotificationType = "issue_created"
17 NotificationTypeIssueCommented NotificationType = "issue_commented"
18 NotificationTypePullCreated NotificationType = "pull_created"
19 NotificationTypePullCommented NotificationType = "pull_commented"
20 NotificationTypeFollowed NotificationType = "followed"
21 NotificationTypePullMerged NotificationType = "pull_merged"
22 NotificationTypeIssueClosed NotificationType = "issue_closed"
23 NotificationTypeIssueReopen NotificationType = "issue_reopen"
24 NotificationTypePullClosed NotificationType = "pull_closed"
25 NotificationTypePullReopen NotificationType = "pull_reopen"
26 NotificationTypeUserMentioned NotificationType = "user_mentioned"
27 NotificationTypeIssueAssigned NotificationType = "issue_assigned"
28 NotificationTypeIssueUnassigned NotificationType = "issue_unassigned"
29 NotificationTypePullAssigned NotificationType = "pull_assigned"
30 NotificationTypePullUnassigned NotificationType = "pull_unassigned"
31)
32
33var SocialNotificationTypes = []NotificationType{
34 NotificationTypeRepoStarred,
35 NotificationTypeFollowed,
36}
37
38var WorkNotificationTypes = []NotificationType{
39 NotificationTypeIssueCreated,
40 NotificationTypeIssueCommented,
41 NotificationTypeIssueClosed,
42 NotificationTypeIssueReopen,
43 NotificationTypePullCreated,
44 NotificationTypePullCommented,
45 NotificationTypePullMerged,
46 NotificationTypePullClosed,
47 NotificationTypePullReopen,
48 NotificationTypeUserMentioned,
49 NotificationTypeIssueAssigned,
50 NotificationTypeIssueUnassigned,
51 NotificationTypePullAssigned,
52 NotificationTypePullUnassigned,
53}
54
55type Notification struct {
56 ID int64
57 RecipientDid string
58 ActorDid string
59 Type NotificationType
60 EntityType string
61 EntityId string
62 Read bool
63 Created time.Time
64
65 // foreign key references
66 RepoId *int64
67 IssueId *int64
68 PullId *int64
69}
70
71// lucide icon that represents this notification
72func (n *Notification) Icon() string {
73 switch n.Type {
74 case NotificationTypeRepoStarred:
75 return "star"
76 case NotificationTypeIssueCreated:
77 return "circle-dot"
78 case NotificationTypeIssueCommented:
79 return "message-square"
80 case NotificationTypeIssueClosed:
81 return "ban"
82 case NotificationTypeIssueReopen:
83 return "circle-dot"
84 case NotificationTypePullCreated:
85 return "git-pull-request-create"
86 case NotificationTypePullCommented:
87 return "message-square"
88 case NotificationTypePullMerged:
89 return "git-merge"
90 case NotificationTypePullClosed:
91 return "git-pull-request-closed"
92 case NotificationTypePullReopen:
93 return "git-pull-request-create"
94 case NotificationTypeFollowed:
95 return "user-plus"
96 case NotificationTypeUserMentioned:
97 return "at-sign"
98 case NotificationTypeIssueAssigned, NotificationTypePullAssigned:
99 return "user-round-arrow-forward"
100 case NotificationTypeIssueUnassigned, NotificationTypePullUnassigned:
101 return "user-round-minus"
102 default:
103 return ""
104 }
105}
106
107type NotificationWithEntity struct {
108 *Notification
109 Repo *Repo
110 Issue *Issue
111 Pull *Pull
112}
113
114// URL returns the navigable path for the notification, resolving DIDs to
115// handles via the provided resolver.
116func (n *NotificationWithEntity) URL(res *idresolver.Resolver) string {
117 resolve := func(did string) string {
118 if id, err := res.ResolveIdent(context.Background(), did); err == nil && !id.Handle.IsInvalidHandle() {
119 return id.Handle.String()
120 }
121 return did
122 }
123
124 switch n.Type {
125 case NotificationTypeFollowed:
126 return "/" + resolve(n.ActorDid)
127 }
128 if n.Repo == nil {
129 return ""
130 }
131 repoHandle := resolve(n.Repo.Did)
132 slug := n.Repo.Slug()
133 switch {
134 case n.Issue != nil:
135 return fmt.Sprintf("/%s/%s/issues/%d", repoHandle, slug, n.Issue.IssueId)
136 case n.Pull != nil:
137 return fmt.Sprintf("/%s/%s/pulls/%d", repoHandle, slug, n.Pull.PullId)
138 default:
139 // repo_starred and other repo-level types
140 return fmt.Sprintf("/%s/%s", repoHandle, slug)
141 }
142}
143
144type NotificationPreferences struct {
145 ID int64
146 UserDid syntax.DID
147 RepoStarred bool
148 IssueCreated bool
149 IssueCommented bool
150 PullCreated bool
151 PullCommented bool
152 Followed bool
153 UserMentioned bool
154 PullMerged bool
155 IssueClosed bool
156 EmailNotifications bool
157}
158
159func (prefs *NotificationPreferences) ShouldNotify(t NotificationType) bool {
160 switch t {
161 case NotificationTypeRepoStarred:
162 return prefs.RepoStarred
163 case NotificationTypeIssueCreated:
164 return prefs.IssueCreated
165 case NotificationTypeIssueCommented:
166 return prefs.IssueCommented
167 case NotificationTypeIssueClosed:
168 return prefs.IssueClosed
169 case NotificationTypeIssueReopen:
170 return prefs.IssueCreated // same pref for now
171 case NotificationTypePullCreated:
172 return prefs.PullCreated
173 case NotificationTypePullCommented:
174 return prefs.PullCommented
175 case NotificationTypePullMerged:
176 return prefs.PullMerged
177 case NotificationTypePullClosed:
178 return prefs.PullMerged // same pref for now
179 case NotificationTypePullReopen:
180 return prefs.PullCreated // same pref for now
181 case NotificationTypeFollowed:
182 return prefs.Followed
183 case NotificationTypeUserMentioned,
184 NotificationTypeIssueAssigned,
185 NotificationTypeIssueUnassigned,
186 NotificationTypePullAssigned,
187 NotificationTypePullUnassigned:
188 return prefs.UserMentioned
189 default:
190 return false
191 }
192}
193
194func DefaultNotificationPreferences(user syntax.DID) *NotificationPreferences {
195 return &NotificationPreferences{
196 UserDid: user,
197 RepoStarred: true,
198 IssueCreated: true,
199 IssueCommented: true,
200 PullCreated: true,
201 PullCommented: true,
202 Followed: true,
203 UserMentioned: true,
204 PullMerged: true,
205 IssueClosed: true,
206 EmailNotifications: false,
207 }
208}