···2627 // optionally, populate this when querying for reverse mappings
28 // like comment counts, parent repo etc.
29- Comments []IssueComment
30 Labels LabelState
31 Repo *Repo
32}
···62}
6364type CommentListItem struct {
65- Self *IssueComment
66- Replies []*IssueComment
67}
6869func (it *CommentListItem) Participants() []syntax.DID {
···8889func (i *Issue) CommentList() []CommentListItem {
90 // Create a map to quickly find comments by their aturi
91- toplevel := make(map[string]*CommentListItem)
92- var replies []*IssueComment
9394 // collect top level comments into the map
95 for _, comment := range i.Comments {
96 if comment.IsTopLevel() {
97- toplevel[comment.AtUri().String()] = &CommentListItem{
98 Self: &comment,
99 }
100 } else {
···115 }
116117 // sort everything
118- sortFunc := func(a, b *IssueComment) bool {
119 return a.Created.Before(b.Created)
120 }
121 sort.Slice(listing, func(i, j int) bool {
···144 addParticipant(i.Did)
145146 for _, c := range i.Comments {
147- addParticipant(c.Did)
148 }
149150 return participants
···171 Open: true, // new issues are open by default
172 }
173}
174-175-type IssueComment struct {
176- Id int64
177- Did string
178- Rkey string
179- IssueAt string
180- ReplyTo *string
181- Body string
182- Created time.Time
183- Edited *time.Time
184- Deleted *time.Time
185- Mentions []syntax.DID
186- References []syntax.ATURI
187-}
188-189-func (i *IssueComment) AtUri() syntax.ATURI {
190- return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", i.Did, tangled.RepoIssueCommentNSID, i.Rkey))
191-}
192-193-func (i *IssueComment) AsRecord() tangled.RepoIssueComment {
194- mentions := make([]string, len(i.Mentions))
195- for i, did := range i.Mentions {
196- mentions[i] = string(did)
197- }
198- references := make([]string, len(i.References))
199- for i, uri := range i.References {
200- references[i] = string(uri)
201- }
202- return tangled.RepoIssueComment{
203- Body: i.Body,
204- Issue: i.IssueAt,
205- CreatedAt: i.Created.Format(time.RFC3339),
206- ReplyTo: i.ReplyTo,
207- Mentions: mentions,
208- References: references,
209- }
210-}
211-212-func (i *IssueComment) IsTopLevel() bool {
213- return i.ReplyTo == nil
214-}
215-216-func (i *IssueComment) IsReply() bool {
217- return i.ReplyTo != nil
218-}
219-220-func IssueCommentFromRecord(did, rkey string, record tangled.RepoIssueComment) (*IssueComment, error) {
221- created, err := time.Parse(time.RFC3339, record.CreatedAt)
222- if err != nil {
223- created = time.Now()
224- }
225-226- ownerDid := did
227-228- if _, err = syntax.ParseATURI(record.Issue); err != nil {
229- return nil, err
230- }
231-232- i := record
233- mentions := make([]syntax.DID, len(record.Mentions))
234- for i, did := range record.Mentions {
235- mentions[i] = syntax.DID(did)
236- }
237- references := make([]syntax.ATURI, len(record.References))
238- for i, uri := range i.References {
239- references[i] = syntax.ATURI(uri)
240- }
241-242- comment := IssueComment{
243- Did: ownerDid,
244- Rkey: rkey,
245- Body: record.Body,
246- IssueAt: record.Issue,
247- ReplyTo: record.ReplyTo,
248- Created: created,
249- Mentions: mentions,
250- References: references,
251- }
252-253- return &comment, nil
254-}
···2627 // optionally, populate this when querying for reverse mappings
28 // like comment counts, parent repo etc.
29+ Comments []Comment
30 Labels LabelState
31 Repo *Repo
32}
···62}
6364type CommentListItem struct {
65+ Self *Comment
66+ Replies []*Comment
67}
6869func (it *CommentListItem) Participants() []syntax.DID {
···8889func (i *Issue) CommentList() []CommentListItem {
90 // Create a map to quickly find comments by their aturi
91+ toplevel := make(map[syntax.ATURI]*CommentListItem)
92+ var replies []*Comment
9394 // collect top level comments into the map
95 for _, comment := range i.Comments {
96 if comment.IsTopLevel() {
97+ toplevel[comment.AtUri()] = &CommentListItem{
98 Self: &comment,
99 }
100 } else {
···115 }
116117 // sort everything
118+ sortFunc := func(a, b *Comment) bool {
119 return a.Created.Before(b.Created)
120 }
121 sort.Slice(listing, func(i, j int) bool {
···144 addParticipant(i.Did)
145146 for _, c := range i.Comments {
147+ addParticipant(c.Did.String())
148 }
149150 return participants
···171 Open: true, // new issues are open by default
172 }
173}
000000000000000000000000000000000000000000000000000000000000000000000000000000000
+4-4
appview/notify/db/db.go
···122 )
123}
124125-func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment, mentions []syntax.DID) {
126- issues, err := db.GetIssues(n.db, orm.FilterEq("at_uri", comment.IssueAt))
127 if err != nil {
128 log.Printf("NewIssueComment: failed to get issues: %v", err)
129 return
130 }
131 if len(issues) == 0 {
132- log.Printf("NewIssueComment: no issue found for %s", comment.IssueAt)
133 return
134 }
135 issue := issues[0]
···147148 // find the parent thread, and add all DIDs from here to the recipient list
149 for _, t := range issue.CommentList() {
150- if t.Self.AtUri().String() == parentAtUri {
151 for _, p := range t.Participants() {
152 recipients.Insert(p)
153 }
···122 )
123}
124125+func (n *databaseNotifier) NewIssueComment(ctx context.Context, comment *models.Comment, mentions []syntax.DID) {
126+ issues, err := db.GetIssues(n.db, orm.FilterEq("at_uri", comment.Subject))
127 if err != nil {
128 log.Printf("NewIssueComment: failed to get issues: %v", err)
129 return
130 }
131 if len(issues) == 0 {
132+ log.Printf("NewIssueComment: no issue found for %s", comment.Subject)
133 return
134 }
135 issue := issues[0]
···147148 // find the parent thread, and add all DIDs from here to the recipient list
149 for _, t := range issue.CommentList() {
150+ if t.Self.AtUri() == parentAtUri {
151 for _, p := range t.Participants() {
152 recipients.Insert(p)
153 }