Monorepo for Tangled tangled.org
855
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview: move `CommentList` out of `Issue`

So that we can render reply comments from non-issue threads.

Signed-off-by: Seongmin Lee <git@boltless.me>

+84 -89
+1 -1
appview/issues/issues.go
··· 144 144 LoggedInUser: user, 145 145 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 146 146 Issue: issue, 147 - CommentList: issue.CommentList(), 147 + CommentList: models.NewCommentList(issue.Comments), 148 148 Backlinks: backlinks, 149 149 Reactions: reactionMap, 150 150 UserReacted: userReactions,
+72
appview/models/comment.go
··· 2 2 3 3 import ( 4 4 "fmt" 5 + "sort" 5 6 "strings" 6 7 "time" 7 8 ··· 157 158 PullRoundIdx: pullRoundIdx, 158 159 }, nil 159 160 } 161 + 162 + type CommentListItem struct { 163 + Self *Comment 164 + Replies []*Comment 165 + } 166 + 167 + func (it *CommentListItem) Participants() []syntax.DID { 168 + participantSet := make(map[syntax.DID]struct{}) 169 + participants := []syntax.DID{} 170 + 171 + addParticipant := func(did syntax.DID) { 172 + if _, exists := participantSet[did]; !exists { 173 + participantSet[did] = struct{}{} 174 + participants = append(participants, did) 175 + } 176 + } 177 + 178 + addParticipant(syntax.DID(it.Self.Did)) 179 + 180 + for _, c := range it.Replies { 181 + addParticipant(syntax.DID(c.Did)) 182 + } 183 + 184 + return participants 185 + } 186 + 187 + func NewCommentList(comments []Comment) []CommentListItem { 188 + // Create a map to quickly find comments by their aturi 189 + toplevel := make(map[syntax.ATURI]*CommentListItem) 190 + var replies []*Comment 191 + 192 + // collect top level comments into the map 193 + for _, comment := range comments { 194 + if comment.IsTopLevel() { 195 + toplevel[comment.AtUri()] = &CommentListItem{ 196 + Self: &comment, 197 + } 198 + } else { 199 + replies = append(replies, &comment) 200 + } 201 + } 202 + 203 + for _, r := range replies { 204 + if r.ReplyTo == nil { 205 + continue 206 + } 207 + if parent, exists := toplevel[syntax.ATURI(r.ReplyTo.Uri)]; exists { 208 + parent.Replies = append(parent.Replies, r) 209 + } 210 + } 211 + 212 + var listing []CommentListItem 213 + for _, v := range toplevel { 214 + listing = append(listing, *v) 215 + } 216 + 217 + // sort everything 218 + sortFunc := func(a, b *Comment) bool { 219 + return a.Created.Before(b.Created) 220 + } 221 + sort.Slice(listing, func(i, j int) bool { 222 + return sortFunc(listing[i].Self, listing[j].Self) 223 + }) 224 + for _, r := range listing { 225 + sort.Slice(r.Replies, func(i, j int) bool { 226 + return sortFunc(r.Replies[i], r.Replies[j]) 227 + }) 228 + } 229 + 230 + return listing 231 + }
-72
appview/models/issue.go
··· 2 2 3 3 import ( 4 4 "fmt" 5 - "sort" 6 5 "time" 7 6 8 7 "github.com/bluesky-social/indigo/atproto/syntax" ··· 64 63 return "open" 65 64 } 66 65 return "closed" 67 - } 68 - 69 - type CommentListItem struct { 70 - Self *Comment 71 - Replies []*Comment 72 - } 73 - 74 - func (it *CommentListItem) Participants() []syntax.DID { 75 - participantSet := make(map[syntax.DID]struct{}) 76 - participants := []syntax.DID{} 77 - 78 - addParticipant := func(did syntax.DID) { 79 - if _, exists := participantSet[did]; !exists { 80 - participantSet[did] = struct{}{} 81 - participants = append(participants, did) 82 - } 83 - } 84 - 85 - addParticipant(syntax.DID(it.Self.Did)) 86 - 87 - for _, c := range it.Replies { 88 - addParticipant(syntax.DID(c.Did)) 89 - } 90 - 91 - return participants 92 - } 93 - 94 - func (i *Issue) CommentList() []CommentListItem { 95 - // Create a map to quickly find comments by their aturi 96 - toplevel := make(map[syntax.ATURI]*CommentListItem) 97 - var replies []*Comment 98 - 99 - // collect top level comments into the map 100 - for _, comment := range i.Comments { 101 - if comment.IsTopLevel() { 102 - toplevel[comment.AtUri()] = &CommentListItem{ 103 - Self: &comment, 104 - } 105 - } else { 106 - replies = append(replies, &comment) 107 - } 108 - } 109 - 110 - for _, r := range replies { 111 - if r.ReplyTo == nil { 112 - continue 113 - } 114 - if parent, exists := toplevel[syntax.ATURI(r.ReplyTo.Uri)]; exists { 115 - parent.Replies = append(parent.Replies, r) 116 - } 117 - } 118 - 119 - var listing []CommentListItem 120 - for _, v := range toplevel { 121 - listing = append(listing, *v) 122 - } 123 - 124 - // sort everything 125 - sortFunc := func(a, b *Comment) bool { 126 - return a.Created.Before(b.Created) 127 - } 128 - sort.Slice(listing, func(i, j int) bool { 129 - return sortFunc(listing[i].Self, listing[j].Self) 130 - }) 131 - for _, r := range listing { 132 - sort.Slice(r.Replies, func(i, j int) bool { 133 - return sortFunc(r.Replies[i], r.Replies[j]) 134 - }) 135 - } 136 - 137 - return listing 138 66 } 139 67 140 68 func (i *Issue) Participants() []syntax.DID {
+1 -1
appview/notify/db/db.go
··· 121 121 parent := *comment.ReplyTo 122 122 123 123 // find the parent thread, and add all DIDs from here to the recipient list 124 - for _, t := range issue.CommentList() { 124 + for _, t := range models.NewCommentList(issue.Comments) { 125 125 if t.Self.AtUri() == syntax.ATURI(parent.Uri) { 126 126 for _, p := range t.Participants() { 127 127 recipients.Insert(p)
+7 -9
appview/pages/templates/repo/issues/fragments/commentList.html appview/pages/templates/fragments/comment/commentList.html
··· 1 - {{ define "repo/issues/fragments/commentList" }} 1 + {{ define "fragments/comment/commentList" }} 2 2 <div class="flex flex-col gap-4"> 3 3 {{ range $item := .CommentList }} 4 4 {{ template "commentListItem" (list $ .) }} ··· 9 9 {{ define "commentListItem" }} 10 10 {{ $root := index . 0 }} 11 11 {{ $item := index . 1 }} 12 - {{ $params := 13 - (dict 14 - "LoggedInUser" $root.LoggedInUser 15 - "VouchRelationship" (index $root.VouchRelationships $item.Self.Did) 16 - "Comment" $item.Self) }} 17 12 18 13 <div class="rounded border border-gray-200 dark:border-gray-700 w-full overflow-hidden shadow-sm bg-gray-50 dark:bg-gray-800/50"> 19 - {{ template "topLevelComment" $params }} 14 + {{ template "topLevelComment" 15 + (dict 16 + "LoggedInUser" $root.LoggedInUser 17 + "VouchRelationship" (index $root.VouchRelationships $item.Self.Did) 18 + "Comment" $item.Self) }} 20 19 21 20 <div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700"> 22 21 {{ range $index, $reply := $item.Replies }} 23 22 <div class="-ml-4"> 24 - {{ 25 - template "replyComment" 23 + {{ template "replyComment" 26 24 (dict 27 25 "LoggedInUser" $root.LoggedInUser 28 26 "VouchRelationship" (index $root.VouchRelationships $reply.Did)
+3 -6
appview/pages/templates/repo/issues/issue.html
··· 114 114 {{ define "repoAfter" }} 115 115 <div class="flex flex-col gap-4 mt-4"> 116 116 {{ 117 - template "repo/issues/fragments/commentList" 117 + template "fragments/comment/commentList" 118 118 (dict 119 - "RepoInfo" $.RepoInfo 120 - "LoggedInUser" $.LoggedInUser 121 - "Issue" $.Issue 122 - "CommentList" $.Issue.CommentList 119 + "LoggedInUser" $.LoggedInUser 123 120 "VouchRelationships" $.VouchRelationships 124 - ) 121 + "CommentList" $.CommentList) 125 122 }} 126 123 127 124 {{ template "repo/issues/fragments/newComment" . }}