···17911791issues.review.content.empty = You need to leave a comment indicating the requested change(s).
17921792issues.review.reject = requested changes %s
17931793issues.review.wait = was requested for review %s
17941794-issues.review.add_review_request = requested review from %s %s
17951795-issues.review.remove_review_request = removed review request for %s %s
17961796-issues.review.remove_review_request_self = refused to review %s
17941794+issues.review.add_review_request = requested review from %[1]s %[2]s
17951795+issues.review.add_review_requests = requested reviews from %[1]s %[2]s
17961796+issues.review.remove_review_request = removed review request for %[1]s %[2]s
17971797+issues.review.remove_review_requests = removed review requests for %[1]s %[2]s
17981798+issues.review.remove_review_request_self = refused to review %[1]s %[2]s
17991799+issues.review.add_remove_review_requests = requested reviews from %[1]s and removed review requests for %[2]s %[3]s
17971800issues.review.pending = Pending
17981801issues.review.pending.tooltip = This comment is not currently visible to other users. To submit your pending comments, select "%s" -> "%s/%s/%s" at the top of the page.
17991802issues.review.review = Review
+122
routers/web/repo/issue.go
···1825182518261826 // Combine multiple label assignments into a single comment
18271827 combineLabelComments(issue)
18281828+ combineRequestReviewComments(issue)
1828182918291830 getBranchData(ctx, issue)
18301831 if issue.IsPull {
···36633664 return ""
36643665 }
36653666 return attachHTML
36673667+}
36683668+36693669+type RequestReviewTarget struct {
36703670+ user *user_model.User
36713671+ team *organization.Team
36723672+}
36733673+36743674+func (t *RequestReviewTarget) ID() int64 {
36753675+ if t.user != nil {
36763676+ return t.user.ID
36773677+ }
36783678+ return t.team.ID
36793679+}
36803680+36813681+func (t *RequestReviewTarget) Name() string {
36823682+ if t.user != nil {
36833683+ return t.user.GetDisplayName()
36843684+ }
36853685+ return t.team.Name
36863686+}
36873687+36883688+func (t *RequestReviewTarget) Type() string {
36893689+ if t.user != nil {
36903690+ return "user"
36913691+ }
36923692+ return "team"
36933693+}
36943694+36953695+// combineRequestReviewComments combine the nearby request review comments as one.
36963696+func combineRequestReviewComments(issue *issues_model.Issue) {
36973697+ var prev, cur *issues_model.Comment
36983698+ for i := 0; i < len(issue.Comments); i++ {
36993699+ cur = issue.Comments[i]
37003700+ if i > 0 {
37013701+ prev = issue.Comments[i-1]
37023702+ }
37033703+ if i == 0 || cur.Type != issues_model.CommentTypeReviewRequest ||
37043704+ (prev != nil && prev.PosterID != cur.PosterID) ||
37053705+ (prev != nil && cur.CreatedUnix-prev.CreatedUnix >= 60) {
37063706+ if cur.Type == issues_model.CommentTypeReviewRequest && (cur.Assignee != nil || cur.AssigneeTeam != nil) {
37073707+ if cur.RemovedAssignee {
37083708+ if cur.AssigneeTeam != nil {
37093709+ cur.RemovedRequestReview = append(cur.RemovedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37103710+ } else {
37113711+ cur.RemovedRequestReview = append(cur.RemovedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37123712+ }
37133713+ } else {
37143714+ if cur.AssigneeTeam != nil {
37153715+ cur.AddedRequestReview = append(cur.AddedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37163716+ } else {
37173717+ cur.AddedRequestReview = append(cur.AddedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37183718+ }
37193719+ }
37203720+ }
37213721+ continue
37223722+ }
37233723+37243724+ // Previous comment is not a review request, so cannot group. Start a new group.
37253725+ if prev.Type != issues_model.CommentTypeReviewRequest {
37263726+ if cur.RemovedAssignee {
37273727+ if cur.AssigneeTeam != nil {
37283728+ cur.RemovedRequestReview = append(cur.RemovedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37293729+ } else {
37303730+ cur.RemovedRequestReview = append(cur.RemovedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37313731+ }
37323732+ } else {
37333733+ if cur.AssigneeTeam != nil {
37343734+ cur.AddedRequestReview = append(cur.AddedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37353735+ } else {
37363736+ cur.AddedRequestReview = append(cur.AddedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37373737+ }
37383738+ }
37393739+ continue
37403740+ }
37413741+37423742+ // Start grouping.
37433743+ if cur.RemovedAssignee {
37443744+ addedIndex := slices.IndexFunc(prev.AddedRequestReview, func(t issues_model.RequestReviewTarget) bool {
37453745+ if cur.AssigneeTeam != nil {
37463746+ return cur.AssigneeTeam.ID == t.ID() && t.Type() == "team"
37473747+ }
37483748+ return cur.Assignee.ID == t.ID() && t.Type() == "user"
37493749+ })
37503750+37513751+ // If for this target a AddedRequestReview, then we remove that entry. If it's not found, then add it to the RemovedRequestReview.
37523752+ if addedIndex == -1 {
37533753+ if cur.AssigneeTeam != nil {
37543754+ prev.RemovedRequestReview = append(prev.RemovedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37553755+ } else {
37563756+ prev.RemovedRequestReview = append(prev.RemovedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37573757+ }
37583758+ } else {
37593759+ prev.AddedRequestReview = slices.Delete(prev.AddedRequestReview, addedIndex, addedIndex+1)
37603760+ }
37613761+ } else {
37623762+ removedIndex := slices.IndexFunc(prev.RemovedRequestReview, func(t issues_model.RequestReviewTarget) bool {
37633763+ if cur.AssigneeTeam != nil {
37643764+ return cur.AssigneeTeam.ID == t.ID() && t.Type() == "team"
37653765+ }
37663766+ return cur.Assignee.ID == t.ID() && t.Type() == "user"
37673767+ })
37683768+37693769+ // If for this target a RemovedRequestReview, then we remove that entry. If it's not found, then add it to the AddedRequestReview.
37703770+ if removedIndex == -1 {
37713771+ if cur.AssigneeTeam != nil {
37723772+ prev.AddedRequestReview = append(prev.AddedRequestReview, &RequestReviewTarget{team: cur.AssigneeTeam})
37733773+ } else {
37743774+ prev.AddedRequestReview = append(prev.AddedRequestReview, &RequestReviewTarget{user: cur.Assignee})
37753775+ }
37763776+ } else {
37773777+ prev.RemovedRequestReview = slices.Delete(prev.RemovedRequestReview, removedIndex, removedIndex+1)
37783778+ }
37793779+ }
37803780+37813781+ // Propoagate creation time.
37823782+ prev.CreatedUnix = cur.CreatedUnix
37833783+37843784+ // Remove the current comment since it has been combined to prev comment
37853785+ issue.Comments = append(issue.Comments[:i], issue.Comments[i+1:]...)
37863786+ i--
37873787+ }
36663788}
3667378936683790// combineLabelComments combine the nearby label comments as one.