mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Show outdated comments in files changed tab (#24936)
If enabled show a clickable label in the comment. A click on the label opens the Conversation tab with the comment focussed - there you're able to view the old diff (or original diff the comment was created on). **Screenshots**   When resolved and outdated:  Option to enable/disable this (stored in user settings - default is disabled):   fixes #24913 --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
		| @@ -18,11 +18,11 @@ import ( | ||||
| type CodeComments map[string]map[int64][]*Comment | ||||
|  | ||||
| // FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line | ||||
| func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) { | ||||
| 	return fetchCodeCommentsByReview(ctx, issue, currentUser, nil) | ||||
| func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User, showOutdatedComments bool) (CodeComments, error) { | ||||
| 	return fetchCodeCommentsByReview(ctx, issue, currentUser, nil, showOutdatedComments) | ||||
| } | ||||
|  | ||||
| func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) { | ||||
| func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) (CodeComments, error) { | ||||
| 	pathToLineToComment := make(CodeComments) | ||||
| 	if review == nil { | ||||
| 		review = &Review{ID: 0} | ||||
| @@ -33,7 +33,7 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u | ||||
| 		ReviewID: review.ID, | ||||
| 	} | ||||
|  | ||||
| 	comments, err := findCodeComments(ctx, opts, issue, currentUser, review) | ||||
| 	comments, err := findCodeComments(ctx, opts, issue, currentUser, review, showOutdatedComments) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -47,15 +47,17 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u | ||||
| 	return pathToLineToComment, nil | ||||
| } | ||||
|  | ||||
| func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) { | ||||
| func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) ([]*Comment, error) { | ||||
| 	var comments CommentList | ||||
| 	if review == nil { | ||||
| 		review = &Review{ID: 0} | ||||
| 	} | ||||
| 	conds := opts.ToConds() | ||||
| 	if review.ID == 0 { | ||||
|  | ||||
| 	if !showOutdatedComments && review.ID == 0 { | ||||
| 		conds = conds.And(builder.Eq{"invalidated": false}) | ||||
| 	} | ||||
|  | ||||
| 	e := db.GetEngine(ctx) | ||||
| 	if err := e.Where(conds). | ||||
| 		Asc("comment.created_unix"). | ||||
| @@ -118,12 +120,12 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu | ||||
| } | ||||
|  | ||||
| // FetchCodeCommentsByLine fetches the code comments for a given treePath and line number | ||||
| func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) { | ||||
| func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64, showOutdatedComments bool) ([]*Comment, error) { | ||||
| 	opts := FindCommentsOptions{ | ||||
| 		Type:     CommentTypeCode, | ||||
| 		IssueID:  issue.ID, | ||||
| 		TreePath: treePath, | ||||
| 		Line:     line, | ||||
| 	} | ||||
| 	return findCodeComments(ctx, opts, issue, currentUser, nil) | ||||
| 	return findCodeComments(ctx, opts, issue, currentUser, nil, showOutdatedComments) | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,7 @@ func TestFetchCodeComments(t *testing.T) { | ||||
|  | ||||
| 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) | ||||
| 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) | ||||
| 	res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user) | ||||
| 	res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user, false) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Contains(t, res, "README.md") | ||||
| 	assert.Contains(t, res["README.md"], int64(4)) | ||||
| @@ -58,7 +58,7 @@ func TestFetchCodeComments(t *testing.T) { | ||||
| 	assert.Equal(t, int64(4), res["README.md"][4][0].ID) | ||||
|  | ||||
| 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) | ||||
| 	res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2) | ||||
| 	res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2, false) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, res, 1) | ||||
| } | ||||
|   | ||||
| @@ -141,7 +141,7 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) { | ||||
| 	if err = r.loadIssue(ctx); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r) | ||||
| 	r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,8 @@ const ( | ||||
| 	SettingsKeyHiddenCommentTypes = "issue.hidden_comment_types" | ||||
| 	// SettingsKeyDiffWhitespaceBehavior is the setting key for whitespace behavior of diff | ||||
| 	SettingsKeyDiffWhitespaceBehavior = "diff.whitespace_behaviour" | ||||
| 	// SettingsKeyShowOutdatedComments is the setting key wether or not to show outdated comments in PRs | ||||
| 	SettingsKeyShowOutdatedComments = "comment_code.show_outdated" | ||||
| 	// UserActivityPubPrivPem is user's private key | ||||
| 	UserActivityPubPrivPem = "activitypub.priv_pem" | ||||
| 	// UserActivityPubPubPem is user's public key | ||||
|   | ||||
| @@ -1611,6 +1611,9 @@ issues.review.pending.tooltip = This comment is not currently visible to other u | ||||
| issues.review.review = Review | ||||
| issues.review.reviewers = Reviewers | ||||
| issues.review.outdated = Outdated | ||||
| issues.review.outdated_description = Content has changed since this comment was made | ||||
| issues.review.option.show_outdated_comments = Show outdated comments | ||||
| issues.review.option.hide_outdated_comments = Hide outdated comments | ||||
| issues.review.show_outdated = Show outdated | ||||
| issues.review.hide_outdated = Hide outdated | ||||
| issues.review.show_resolved = Show resolved | ||||
|   | ||||
| @@ -5,6 +5,7 @@ package repo | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
|  | ||||
| 	system_model "code.gitea.io/gitea/models/system" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| @@ -88,3 +89,27 @@ func SetWhitespaceBehavior(ctx *context.Context) { | ||||
| 		ctx.Data["WhitespaceBehavior"] = whitespaceBehavior | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SetShowOutdatedComments set the show outdated comments option as context variable | ||||
| func SetShowOutdatedComments(ctx *context.Context) { | ||||
| 	showOutdatedCommentsValue := ctx.FormString("show-outdated") | ||||
| 	// var showOutdatedCommentsValue string | ||||
|  | ||||
| 	if showOutdatedCommentsValue != "true" && showOutdatedCommentsValue != "false" { | ||||
| 		// invalid or no value for this form string -> use default or stored user setting | ||||
| 		if ctx.IsSigned { | ||||
| 			showOutdatedCommentsValue, _ = user_model.GetUserSetting(ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, "false") | ||||
| 		} else { | ||||
| 			// not logged in user -> use the default value | ||||
| 			showOutdatedCommentsValue = "false" | ||||
| 		} | ||||
| 	} else { | ||||
| 		// valid value -> update user setting if user is logged in | ||||
| 		if ctx.IsSigned { | ||||
| 			_ = user_model.SetUserSetting(ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, showOutdatedCommentsValue) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	showOutdatedComments, _ := strconv.ParseBool(showOutdatedCommentsValue) | ||||
| 	ctx.Data["ShowOutdatedComments"] = showOutdatedComments | ||||
| } | ||||
|   | ||||
| @@ -761,7 +761,7 @@ func ViewPullFiles(ctx *context.Context) { | ||||
| 		"numberOfViewedFiles": diff.NumViewedFiles, | ||||
| 	} | ||||
|  | ||||
| 	if err = diff.LoadComments(ctx, issue, ctx.Doer); err != nil { | ||||
| 	if err = diff.LoadComments(ctx, issue, ctx.Doer, ctx.Data["ShowOutdatedComments"].(bool)); err != nil { | ||||
| 		ctx.ServerError("LoadComments", err) | ||||
| 		return | ||||
| 	} | ||||
|   | ||||
| @@ -159,7 +159,7 @@ func UpdateResolveConversation(ctx *context.Context) { | ||||
| } | ||||
|  | ||||
| func renderConversation(ctx *context.Context, comment *issues_model.Comment) { | ||||
| 	comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line) | ||||
| 	comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, ctx.Data["ShowOutdatedComments"].(bool)) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("FetchCodeCommentsByLine", err) | ||||
| 		return | ||||
|   | ||||
| @@ -1037,7 +1037,7 @@ func registerRoutes(m *web.Route) { | ||||
| 			m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview) | ||||
| 			m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus) | ||||
| 			m.Post("/delete", reqRepoAdmin, repo.BatchDeleteIssues) | ||||
| 			m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.UpdateResolveConversation) | ||||
| 			m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.SetShowOutdatedComments, repo.UpdateResolveConversation) | ||||
| 			m.Post("/attachments", repo.UploadIssueAttachment) | ||||
| 			m.Post("/attachments/remove", repo.DeleteAttachment) | ||||
| 			m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin) | ||||
| @@ -1285,10 +1285,10 @@ func registerRoutes(m *web.Route) { | ||||
| 			m.Post("/set_allow_maintainer_edit", web.Bind(forms.UpdateAllowEditsForm{}), repo.SetAllowEdits) | ||||
| 			m.Post("/cleanup", context.RepoMustNotBeArchived(), context.RepoRef(), repo.CleanUpPullRequest) | ||||
| 			m.Group("/files", func() { | ||||
| 				m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.ViewPullFiles) | ||||
| 				m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFiles) | ||||
| 				m.Group("/reviews", func() { | ||||
| 					m.Get("/new_comment", repo.RenderNewCodeCommentForm) | ||||
| 					m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.CreateCodeComment) | ||||
| 					m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.SetShowOutdatedComments, repo.CreateCodeComment) | ||||
| 					m.Post("/submit", web.Bind(forms.SubmitReviewForm{}), repo.SubmitReview) | ||||
| 				}, context.RepoMustNotBeArchived()) | ||||
| 			}) | ||||
|   | ||||
| @@ -450,8 +450,8 @@ type Diff struct { | ||||
| } | ||||
|  | ||||
| // LoadComments loads comments into each line | ||||
| func (diff *Diff) LoadComments(ctx context.Context, issue *issues_model.Issue, currentUser *user_model.User) error { | ||||
| 	allComments, err := issues_model.FetchCodeComments(ctx, issue, currentUser) | ||||
| func (diff *Diff) LoadComments(ctx context.Context, issue *issues_model.Issue, currentUser *user_model.User, showOutdatedComments bool) error { | ||||
| 	allComments, err := issues_model.FetchCodeComments(ctx, issue, currentUser, showOutdatedComments) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
| @@ -594,16 +594,26 @@ func setupDefaultDiff() *Diff { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestDiff_LoadComments(t *testing.T) { | ||||
| func TestDiff_LoadCommentsNoOutdated(t *testing.T) { | ||||
| 	assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
|  | ||||
| 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) | ||||
| 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) | ||||
| 	diff := setupDefaultDiff() | ||||
| 	assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user)) | ||||
| 	assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, false)) | ||||
| 	assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 2) | ||||
| } | ||||
|  | ||||
| func TestDiff_LoadCommentsWithOutdated(t *testing.T) { | ||||
| 	assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
|  | ||||
| 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) | ||||
| 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) | ||||
| 	diff := setupDefaultDiff() | ||||
| 	assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, true)) | ||||
| 	assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 3) | ||||
| } | ||||
|  | ||||
| func TestDiffLine_CanComment(t *testing.T) { | ||||
| 	assert.False(t, (&DiffLine{Type: DiffLineSection}).CanComment()) | ||||
| 	assert.False(t, (&DiffLine{Type: DiffLineAdd, Comments: []*issues_model.Comment{{Content: "bla"}}}).CanComment()) | ||||
|   | ||||
| @@ -31,6 +31,12 @@ | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 			<div class="comment-header-right actions gt-df gt-ac"> | ||||
| 				{{if .Invalidated}} | ||||
| 					{{$referenceUrl := printf "%s#%s" $.root.Issue.Link .HashTag}} | ||||
| 					<a href="{{AppSubUrl}}{{$referenceUrl}}" class="ui label basic small" data-tooltip-content="{{$.root.locale.Tr "repo.issues.review.outdated_description"}}"> | ||||
| 						{{$.root.locale.Tr "repo.issues.review.outdated"}} | ||||
| 					</a> | ||||
| 				{{end}} | ||||
| 				{{if and .Review}} | ||||
| 					{{if eq .Review.Type 0}} | ||||
| 						<div class="ui label basic small yellow pending-label" data-tooltip-content="{{$.root.locale.Tr "repo.issues.review.pending.tooltip" ($.root.locale.Tr "repo.diff.review") ($.root.locale.Tr "repo.diff.review.approve") ($.root.locale.Tr "repo.diff.review.comment") ($.root.locale.Tr "repo.diff.review.reject")}}"> | ||||
|   | ||||
| @@ -1,14 +1,25 @@ | ||||
| {{$resolved := (index .comments 0).IsResolved}} | ||||
| {{$invalid := (index .comments 0).Invalidated}} | ||||
| {{$resolveDoer := (index .comments 0).ResolveDoer}} | ||||
| {{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}} | ||||
| {{$referenceUrl := printf "%s#%s" $.Issue.Link (index .comments 0).HashTag}} | ||||
| <div class="conversation-holder" data-path="{{(index .comments 0).TreePath}}" data-side="{{if lt (index .comments 0).Line 0}}left{{else}}right{{end}}" data-idx="{{(index .comments 0).UnsignedLine}}"> | ||||
| 	{{if $resolved}} | ||||
| 		<div class="ui attached header resolved-placeholder gt-df gt-ac gt-sb"> | ||||
| 			<div class="ui grey text"> | ||||
| 			<div class="ui grey text gt-df gt-ac gt-fw gt-gap-2"> | ||||
| 				{{svg "octicon-check" 16 "icon gt-mr-2"}} | ||||
| 				<b>{{$resolveDoer.Name}}</b> {{$.locale.Tr "repo.issues.review.resolved_by"}} | ||||
| 				{{if $invalid}} | ||||
| 					<!-- | ||||
| 					We only handle the case $resolved=true and $invalid=true in this template because if the comment is not resolved it has the outdated label in the comments area (not the header above). | ||||
| 					The case $resolved=false and $invalid=true is handled in repo/diff/comments.tmpl | ||||
| 					--> | ||||
| 					<a href="{{AppSubUrl}}{{$referenceUrl}}" class="ui label basic small gt-ml-3" data-tooltip-content="{{$.locale.Tr "repo.issues.review.outdated_description"}}"> | ||||
| 						{{$.locale.Tr "repo.issues.review.outdated"}} | ||||
| 					</a> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 			<div> | ||||
| 			<div class="gt-df gt-ac gt-gap-3"> | ||||
| 				<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny labeled button show-outdated gt-df gt-ac"> | ||||
| 					{{svg "octicon-unfold" 16 "gt-mr-3"}} | ||||
| 					{{$.locale.Tr "repo.issues.review.show_resolved"}} | ||||
|   | ||||
| @@ -14,5 +14,20 @@ | ||||
| 		{{end}} | ||||
| 		<a id="expand-files-btn" class="item">{{.locale.Tr "repo.pulls.expand_files"}}</a> | ||||
| 		<a id="collapse-files-btn"class="item">{{.locale.Tr "repo.pulls.collapse_files"}}</a> | ||||
| 		{{if .Issue.Index}} | ||||
| 			{{if .ShowOutdatedComments}} | ||||
| 				<a class="item" href="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated=false"> | ||||
| 					<label class="gt-pointer-events-none"> | ||||
| 						{{.locale.Tr "repo.issues.review.option.hide_outdated_comments"}} | ||||
| 					</label> | ||||
| 				</a> | ||||
| 			{{else}} | ||||
| 				<a class="item" href="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated=true"> | ||||
| 					<label class="gt-pointer-events-none"> | ||||
| 						{{.locale.Tr "repo.issues.review.option.show_outdated_comments"}} | ||||
| 					</label> | ||||
| 				</a> | ||||
| 			{{end}} | ||||
| 		{{end}} | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,25 +1,25 @@ | ||||
| <div class="ui dropdown tiny basic button" data-tooltip-content="{{.locale.Tr "repo.diff.whitespace_button"}}"> | ||||
| 	{{svg "gitea-whitespace"}} | ||||
| 	<div class="menu"> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=show-all"> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=show-all&show-outdated={{$.ShowOutdatedComments}}"> | ||||
| 			<label class="gt-pointer-events-none"> | ||||
| 				<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "show-all"}} checked{{end}}> | ||||
| 				{{.locale.Tr "repo.diff.whitespace_show_everything"}} | ||||
| 			</label> | ||||
| 		</a> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-all"> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-all&show-outdated={{$.ShowOutdatedComments}}"> | ||||
| 			<label class="gt-pointer-events-none"> | ||||
| 				<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-all"}} checked{{end}}> | ||||
| 				{{.locale.Tr "repo.diff.whitespace_ignore_all_whitespace"}} | ||||
| 			</label> | ||||
| 		</a> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-change"> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-change&show-outdated={{$.ShowOutdatedComments}}"> | ||||
| 			<label class="gt-pointer-events-none"> | ||||
| 				<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-change"}} checked{{end}}> | ||||
| 				{{.locale.Tr "repo.diff.whitespace_ignore_amount_changes"}} | ||||
| 			</label> | ||||
| 		</a> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-eol"> | ||||
| 		<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-eol&show-outdated={{$.ShowOutdatedComments}}"> | ||||
| 			<label class="gt-pointer-events-none"> | ||||
| 				<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-eol"}} checked{{end}}> | ||||
| 				{{.locale.Tr "repo.diff.whitespace_ignore_at_eol"}} | ||||
| @@ -27,4 +27,4 @@ | ||||
| 		</a> | ||||
| 	</div> | ||||
| </div> | ||||
| <a class="ui tiny basic button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a> | ||||
| <a class="ui tiny basic button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated={{$.ShowOutdatedComments}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a> | ||||
|   | ||||
| @@ -488,7 +488,7 @@ | ||||
| 										<div class="gt-df gt-ac"> | ||||
| 											<a href="{{(index $comms 0).CodeCommentLink}}" class="file-comment gt-ml-3 gt-word-break">{{$filename}}</a> | ||||
| 											{{if $invalid}} | ||||
| 												<span class="ui label basic small gt-ml-3"> | ||||
| 												<span class="ui label basic small gt-ml-3" data-tooltip-content="{{$.locale.Tr "repo.issues.review.outdated_description"}}"> | ||||
| 													{{$.locale.Tr "repo.issues.review.outdated"}} | ||||
| 												</span> | ||||
| 											{{end}} | ||||
|   | ||||
| @@ -1702,6 +1702,10 @@ | ||||
| .repository .diff-box .resolved-placeholder { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   font-size: 14px !important; | ||||
|   height: 36px; | ||||
|   padding-top: 0; | ||||
|   padding-bottom: 0; | ||||
| } | ||||
|  | ||||
| .repository .diff-box .resolved-placeholder .button { | ||||
| @@ -1728,10 +1732,6 @@ | ||||
|   text-align: center; | ||||
| } | ||||
|  | ||||
| .repository .diff-file-box .code-diff { | ||||
|   font-size: 12px; | ||||
| } | ||||
|  | ||||
| .repository .diff-file-box .code-diff td { | ||||
|   padding: 0 0 0 10px !important; | ||||
|   border-top: 0; | ||||
| @@ -2495,14 +2495,17 @@ | ||||
|   left: 7px; | ||||
| } | ||||
|  | ||||
| .comment-header .actions a { | ||||
|   margin-right: 0 !important; | ||||
| .comment-header .actions a:not(.label) { | ||||
|   padding: 0.5rem !important; | ||||
| } | ||||
|  | ||||
| .comment-header-left > * + *, | ||||
| .comment-header-right > * + * { | ||||
|   margin-left: 0.25rem; | ||||
| .comment-header .actions .label { | ||||
|   margin: 0 !important; | ||||
| } | ||||
|  | ||||
| .comment-header-left, | ||||
| .comment-header-right { | ||||
|   gap: 4px; | ||||
| } | ||||
|  | ||||
| .comment-body { | ||||
|   | ||||
| @@ -128,7 +128,7 @@ | ||||
| } | ||||
|  | ||||
| .comment-code-cloud .attached.header { | ||||
|   padding: 0.1rem 1rem; | ||||
|   padding: 1px 8px 1px 12px; | ||||
| } | ||||
|  | ||||
| .comment-code-cloud .attached.header .text { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user