Compare commits

..

No commits in common. "22911a1ece5bd08648e10b7ffcb3308d204180ee" and "301de3ab6b505bccdc3ee94c216e4d44bf508ff2" have entirely different histories.

15 changed files with 77 additions and 99 deletions

View File

@ -179,7 +179,7 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
} }
// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs // ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead // In most cases, it shouldn't be used. Use AddXxx function instead
func ToTrustedCmdArgs(args []string) TrustedCmdArgs { func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
ret := make(TrustedCmdArgs, len(args)) ret := make(TrustedCmdArgs, len(args))
for i, arg := range args { for i, arg := range args {

View File

@ -332,13 +332,8 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
} }
func commitAndSignNoAuthor(ctx *mergeContext, message string) error { func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
cmdCommit := git.NewCommand(ctx, "commit").AddOptionFormat("--message=%s", message) if err := git.NewCommand(ctx, "commit").AddArguments(ctx.signArg...).AddOptionFormat("--message=%s", message).
if ctx.signKeyID == "" { Run(ctx.RunOpts()); err != nil {
cmdCommit.AddArguments("--no-gpg-sign")
} else {
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
}
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
} }

View File

@ -28,7 +28,7 @@ type mergeContext struct {
doer *user_model.User doer *user_model.User
sig *git.Signature sig *git.Signature
committer *git.Signature committer *git.Signature
signKeyID string // empty for no-sign, non-empty to sign signArg git.TrustedCmdArgs
env []string env []string
} }
@ -85,10 +85,12 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
// Determine if we should sign // Determine if we should sign
sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch) sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch)
if sign { if sign {
mergeCtx.signKeyID = keyID mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"-S" + keyID})
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
mergeCtx.committer = signer mergeCtx.committer = signer
} }
} else {
mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"--no-gpg-sign"})
} }
commitTimeStr := time.Now().Format(time.RFC3339) commitTimeStr := time.Now().Format(time.RFC3339)
@ -134,11 +136,18 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
return fmt.Errorf("Unable to close .git/info/sparse-checkout file in tmpBasePath: %w", err) return fmt.Errorf("Unable to close .git/info/sparse-checkout file in tmpBasePath: %w", err)
} }
gitConfigCommand := func() *git.Command {
return git.NewCommand(ctx, "config", "--local")
}
setConfig := func(key, value string) error { setConfig := func(key, value string) error {
if err := git.NewCommand(ctx, "config", "--local").AddDynamicArguments(key, value). if err := gitConfigCommand().AddArguments(git.ToTrustedCmdArgs([]string{key, value})...).
Run(ctx.RunOpts()); err != nil { Run(ctx.RunOpts()); err != nil {
log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) if value == "" {
return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) value = "<>"
}
log.Error("git config [%s -> %s ]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git config [%s -> %s ]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
} }
ctx.outbuf.Reset() ctx.outbuf.Reset()
ctx.errbuf.Reset() ctx.errbuf.Reset()

View File

@ -14,8 +14,8 @@ import (
// doMergeStyleSquash squashes the tracking branch on the current HEAD (=base) // doMergeStyleSquash squashes the tracking branch on the current HEAD (=base)
func doMergeStyleSquash(ctx *mergeContext, message string) error { func doMergeStyleSquash(ctx *mergeContext, message string) error {
cmdMerge := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch) cmd := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmdMerge); err != nil { if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmd); err != nil {
log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err) log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err)
return err return err
} }
@ -25,22 +25,28 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error {
return fmt.Errorf("LoadPoster: %w", err) return fmt.Errorf("LoadPoster: %w", err)
} }
sig := ctx.pr.Issue.Poster.NewGitSig() sig := ctx.pr.Issue.Poster.NewGitSig()
if len(ctx.signArg) == 0 {
if err := git.NewCommand(ctx, "commit").
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
AddOptionFormat("--message=%s", message).
Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
}
} else {
if setting.Repository.PullRequest.AddCoCommitterTrailers && ctx.committer.String() != sig.String() { if setting.Repository.PullRequest.AddCoCommitterTrailers && ctx.committer.String() != sig.String() {
// add trailer // add trailer
message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String()) message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
} }
cmdCommit := git.NewCommand(ctx, "commit"). if err := git.NewCommand(ctx, "commit").
AddArguments(ctx.signArg...).
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
AddOptionFormat("--message=%s", message) AddOptionFormat("--message=%s", message).
if ctx.signKeyID == "" { Run(ctx.RunOpts()); err != nil {
cmdCommit.AddArguments("--no-gpg-sign")
} else {
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
}
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
} }
}
ctx.outbuf.Reset() ctx.outbuf.Reset()
ctx.errbuf.Reset() ctx.errbuf.Reset()
return nil return nil

View File

@ -1,4 +1,4 @@
<nav class="ui container" id="navbar" aria-label="{{.locale.Tr "aria.navbar"}}"> <div class="ui container" id="navbar" role="navigation" aria-label="{{.locale.Tr "aria.navbar"}}">
{{$notificationUnreadCount := 0}} {{$notificationUnreadCount := 0}}
{{if .IsSigned}} {{if .IsSigned}}
{{if .NotificationUnreadCount}}{{$notificationUnreadCount = call .NotificationUnreadCount}}{{end}} {{if .NotificationUnreadCount}}{{$notificationUnreadCount = call .NotificationUnreadCount}}{{end}}
@ -150,7 +150,7 @@
</div><!-- end content create new menu --> </div><!-- end content create new menu -->
</div><!-- end dropdown menu create new --> </div><!-- end dropdown menu create new -->
<div class="ui dropdown jump item tooltip gt-mx-0" data-content="{{.locale.Tr "user_profile_and_more"}}"> <div class="ui dropdown jump item tooltip gt-mx-0" tabindex="-1" data-content="{{.locale.Tr "user_profile_and_more"}}">
<span class="text"> <span class="text">
{{avatar $.Context .SignedUser 24 "tiny"}} {{avatar $.Context .SignedUser 24 "tiny"}}
<span class="sr-only">{{.locale.Tr "user_profile_and_more"}}</span> <span class="sr-only">{{.locale.Tr "user_profile_and_more"}}</span>
@ -190,14 +190,14 @@
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin"> <a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin">
{{svg "octicon-server"}} {{svg "octicon-server"}}
{{.locale.Tr "admin_panel"}} {{.locale.Tr "admin_panel"}}<!-- Admin Panel -->
</a> </a>
{{end}} {{end}}
<div class="divider"></div> <div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/"> <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/">
{{svg "octicon-sign-out"}} {{svg "octicon-sign-out"}}
{{.locale.Tr "sign_out"}} {{.locale.Tr "sign_out"}}<!-- Sign Out -->
</a> </a>
</div><!-- end content avatar menu --> </div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu --> </div><!-- end dropdown avatar menu -->
@ -213,6 +213,6 @@
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}"> <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}">
{{svg "octicon-sign-in"}} {{.locale.Tr "sign_in"}} {{svg "octicon-sign-in"}} {{.locale.Tr "sign_in"}}
</a> </a>
</div><!-- end anonymous user right menu --> </div><!-- end anonymous right menu -->
{{end}} {{end}}
</nav> </div>

View File

@ -216,7 +216,7 @@
<div class="gt-df gt-ac"> <div class="gt-df gt-ac">
{{if .Verification.Verified}} {{if .Verification.Verified}}
{{if ne .Verification.SigningUser.ID 0}} {{if ne .Verification.SigningUser.ID 0}}
{{svg "octicon-verified" 16 "gt-mr-3"}} {{svg "octicon-shield-check" 16 "gt-mr-3"}}
{{if .Verification.SigningSSHKey}} {{if .Verification.SigningSSHKey}}
<span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span> <span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
{{.Verification.SigningSSHKey.Fingerprint}} {{.Verification.SigningSSHKey.Fingerprint}}
@ -225,7 +225,7 @@
{{.Verification.SigningKey.PaddedKeyID}} {{.Verification.SigningKey.PaddedKeyID}}
{{end}} {{end}}
{{else}} {{else}}
{{svg "octicon-unverified" 16 "gt-mr-3"}} {{svg "octicon-shield-lock" 16 "gt-mr-3"}}
{{if .Verification.SigningSSHKey}} {{if .Verification.SigningSSHKey}}
<span class="ui text gt-mr-3 tooltip" data-content="{{.locale.Tr "gpg.default_key"}}">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span> <span class="ui text gt-mr-3 tooltip" data-content="{{.locale.Tr "gpg.default_key"}}">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
{{.Verification.SigningSSHKey.Fingerprint}} {{.Verification.SigningSSHKey.Fingerprint}}
@ -235,7 +235,7 @@
{{end}} {{end}}
{{end}} {{end}}
{{else if .Verification.Warning}} {{else if .Verification.Warning}}
{{svg "octicon-unverified" 16 "gt-mr-3"}} {{svg "octicon-shield" 16 "gt-mr-3"}}
{{if .Verification.SigningSSHKey}} {{if .Verification.SigningSSHKey}}
<span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span> <span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
{{.Verification.SigningSSHKey.Fingerprint}} {{.Verification.SigningSSHKey.Fingerprint}}
@ -246,14 +246,14 @@
{{else}} {{else}}
{{if .Verification.SigningKey}} {{if .Verification.SigningKey}}
{{if ne .Verification.SigningKey.KeyID ""}} {{if ne .Verification.SigningKey.KeyID ""}}
{{svg "octicon-verified" 16 "gt-mr-3"}} {{svg "octicon-shield" 16 "gt-mr-3"}}
<span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.gpg_key_id"}}:</span> <span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.gpg_key_id"}}:</span>
{{.Verification.SigningKey.PaddedKeyID}} {{.Verification.SigningKey.PaddedKeyID}}
{{end}} {{end}}
{{end}} {{end}}
{{if .Verification.SigningSSHKey}} {{if .Verification.SigningSSHKey}}
{{if ne .Verification.SigningSSHKey.Fingerprint ""}} {{if ne .Verification.SigningSSHKey.Fingerprint ""}}
{{svg "octicon-verified" 16 "gt-mr-3"}} {{svg "octicon-shield" 16 "gt-mr-3"}}
<span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span> <span class="ui text gt-mr-3">{{.locale.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
{{.Verification.SigningSSHKey.Fingerprint}} {{.Verification.SigningSSHKey.Fingerprint}}
{{end}} {{end}}

View File

@ -24,7 +24,7 @@
{{svg "octicon-diff" 16 "gt-mr-2"}}{{.locale.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}} {{svg "octicon-diff" 16 "gt-mr-2"}}{{.locale.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}}
</div> </div>
</div> </div>
<div class="diff-detail-actions gt-df gt-ac"> <div class="diff-detail-actions gt-df gt-ac gt-w-100">
{{if and .PageIsPullFiles $.SignedUserID (not .IsArchived)}} {{if and .PageIsPullFiles $.SignedUserID (not .IsArchived)}}
<progress id="viewed-files-summary" class="gt-mr-2" value="{{.Diff.NumViewedFiles}}" max="{{.Diff.NumFiles}}"></progress> <progress id="viewed-files-summary" class="gt-mr-2" value="{{.Diff.NumViewedFiles}}" max="{{.Diff.NumFiles}}"></progress>
<label for="viewed-files-summary" id="viewed-files-summary-label" class="gt-mr-3 gt-f1" data-text-changed-template="{{.locale.Tr "repo.pulls.viewed_files_label"}}"> <label for="viewed-files-summary" id="viewed-files-summary-label" class="gt-mr-3 gt-f1" data-text-changed-template="{{.locale.Tr "repo.pulls.viewed_files_label"}}">
@ -161,8 +161,7 @@
{{end}} {{end}}
</div> </div>
{{if $showFileViewToggle}} {{if $showFileViewToggle}}
{{/* for image or CSV, it can have a horizontal scroll bar, there won't be review comment context menu (position absolute) which would be clipped by "overflow" */}} <div id="diff-rendered-{{$file.NameHash}}" class="file-body file-code {{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}">
<div id="diff-rendered-{{$file.NameHash}}" class="file-body file-code {{if $.IsSplitStyle}}code-diff-split{{else}}code-diff-unified{{end}} gt-overflow-x-scroll">
<table class="chroma gt-w-100"> <table class="chroma gt-w-100">
{{if $isImage}} {{if $isImage}}
{{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}}

View File

@ -4,7 +4,7 @@
<span class="ui small label review-comments-counter" data-pending-comment-number="{{.PendingCodeCommentNumber}}">{{.PendingCodeCommentNumber}}</span> <span class="ui small label review-comments-counter" data-pending-comment-number="{{.PendingCodeCommentNumber}}">{{.PendingCodeCommentNumber}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button> </button>
<div class="review-box-panel tippy-target"> <div class="review-box-panel gt-hidden">
<div class="ui segment"> <div class="ui segment">
<form class="ui form" action="{{.Link}}/reviews/submit" method="post"> <form class="ui form" action="{{.Link}}/reviews/submit" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}

View File

@ -58,7 +58,7 @@
</div> </div>
<div class="content"> <div class="content">
{{if .Verified}} {{if .Verified}}
<span class="tooltip" data-content="{{$.locale.Tr "settings.gpg_key_verified_long"}}">{{svg "octicon-verified"}} <strong>{{$.locale.Tr "settings.gpg_key_verified"}}</strong></span> <span class="tooltip" data-content="{{$.locale.Tr "settings.gpg_key_verified_long"}}">{{svg "octicon-shield-check"}} <strong>{{$.locale.Tr "settings.gpg_key_verified"}}</strong></span>
{{end}} {{end}}
{{if gt (len .Emails) 0}} {{if gt (len .Emails) 0}}
<span class="tooltip" data-content="{{$.locale.Tr "settings.gpg_key_matched_identities_long"}}">{{svg "octicon-mail"}} {{$.locale.Tr "settings.gpg_key_matched_identities"}} {{range .Emails}}<strong>{{.Email}} </strong>{{end}}</span> <span class="tooltip" data-content="{{$.locale.Tr "settings.gpg_key_matched_identities_long"}}">{{svg "octicon-mail"}} {{$.locale.Tr "settings.gpg_key_matched_identities"}} {{range .Emails}}<strong>{{.Email}} </strong>{{end}}</span>

View File

@ -51,7 +51,7 @@
</div> </div>
<div class="content"> <div class="content">
{{if .Verified}} {{if .Verified}}
<span class="tooltip" data-content="{{$.locale.Tr "settings.ssh_key_verified_long"}}">{{svg "octicon-verified"}} <strong>{{$.locale.Tr "settings.ssh_key_verified"}}</strong></span> <span class="tooltip" data-content="{{$.locale.Tr "settings.ssh_key_verified_long"}}">{{svg "octicon-shield-check"}} <strong>{{$.locale.Tr "settings.ssh_key_verified"}}</strong></span>
{{end}} {{end}}
<strong>{{.Name}}</strong> <strong>{{.Name}}</strong>
<div class="print meta"> <div class="print meta">

View File

@ -1231,7 +1231,7 @@ a.ui.card:hover,
/* enable fluid page widths for medium size viewports */ /* enable fluid page widths for medium size viewports */
@media (min-width: 768px) and (max-width: 1200px) { @media (min-width: 768px) and (max-width: 1200px) {
.ui.ui.ui.container:not(.fluid) { .ui.ui.ui.container:not(.fluid) {
width: calc(100vw - 64px); width: calc(100vw - 3em);
} }
} }
@ -1285,14 +1285,7 @@ a.ui.card:hover,
.following.bar #navbar { .following.bar #navbar {
width: 100vw; width: 100vw;
min-height: 52px; min-height: 52px;
padding: 0 16px; padding: 0 0.5rem;
}
@media (max-width: 767px) {
.following.bar #navbar {
padding-left: 4px;
padding-right: 0;
}
} }
.following.bar #navbar .brand { .following.bar #navbar .brand {
@ -1498,7 +1491,7 @@ a.ui.card:hover,
} }
.ui.container.fluid.padded { .ui.container.fluid.padded {
padding: 0 32px; padding: 0 10px;
} }
.ui.form .ui.button { .ui.form .ui.button {

View File

@ -22,7 +22,6 @@
/* below class names match Tailwind CSS */ /* below class names match Tailwind CSS */
.gt-pointer-events-none { pointer-events: none !important; } .gt-pointer-events-none { pointer-events: none !important; }
.gt-relative { position: relative !important; } .gt-relative { position: relative !important; }
.gt-overflow-x-scroll { overflow-x: scroll !important; }
.gt-mono { .gt-mono {
font-family: var(--fonts-monospace) !important; font-family: var(--fonts-monospace) !important;

View File

@ -3337,6 +3337,10 @@ td.blob-excerpt {
min-width: 100px; min-width: 100px;
} }
.diff-file-body {
overflow-x: scroll;
}
.diff-stats-bar { .diff-stats-bar {
display: inline-block; display: inline-block;
background-color: var(--color-red); background-color: var(--color-red);

View File

@ -214,10 +214,6 @@ a.blob-excerpt:hover {
color: var(--color-primary-contrast); color: var(--color-primary-contrast);
} }
.review-box-panel .ui.segment {
border: none;
}
/* See the comment of createCommentEasyMDE() for the review editor */ /* See the comment of createCommentEasyMDE() for the review editor */
/* EasyMDE's options can not handle minHeight & maxHeight together correctly, we have to set minHeight in JS code */ /* EasyMDE's options can not handle minHeight & maxHeight together correctly, we have to set minHeight in JS code */
.review-box-panel .CodeMirror-scroll { .review-box-panel .CodeMirror-scroll {
@ -253,6 +249,14 @@ a.blob-excerpt:hover {
position: relative; position: relative;
} }
.review-box-panel {
position: absolute;
min-width: max-content;
top: 45px;
right: -5px;
z-index: 2;
}
#review-box .review-comments-counter { #review-box .review-comments-counter {
background-color: var(--color-primary-light-4); background-color: var(--color-primary-light-4);
color: var(--color-primary-contrast); color: var(--color-primary-contrast);

View File

@ -4,9 +4,8 @@ import {attachTribute} from './tribute.js';
import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js'; import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js';
import {initEasyMDEImagePaste} from './comp/ImagePaste.js'; import {initEasyMDEImagePaste} from './comp/ImagePaste.js';
import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js'; import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
import {initTooltip, showTemporaryTooltip, createTippy} from '../modules/tippy.js'; import {initTooltip, showTemporaryTooltip} from '../modules/tippy.js';
import {hideElem, showElem, toggleElem} from '../utils/dom.js'; import {hideElem, showElem, toggleElem} from '../utils/dom.js';
import {setFileFolding} from './file-fold.js';
const {appSubUrl, csrfToken} = window.config; const {appSubUrl, csrfToken} = window.config;
@ -437,36 +436,17 @@ export async function handleReply($el) {
export function initRepoPullRequestReview() { export function initRepoPullRequestReview() {
if (window.location.hash && window.location.hash.startsWith('#issuecomment-')) { if (window.location.hash && window.location.hash.startsWith('#issuecomment-')) {
// set scrollRestoration to 'manual' when there is a hash in url, so that the scroll position will not be remembered after refreshing
if (window.history.scrollRestoration !== 'manual') {
window.history.scrollRestoration = 'manual';
}
const commentDiv = $(window.location.hash); const commentDiv = $(window.location.hash);
if (commentDiv) { if (commentDiv) {
// get the name of the parent id // get the name of the parent id
const groupID = commentDiv.closest('div[id^="code-comments-"]').attr('id'); const groupID = commentDiv.closest('div[id^="code-comments-"]').attr('id');
if (groupID && groupID.startsWith('code-comments-')) { if (groupID && groupID.startsWith('code-comments-')) {
const id = groupID.slice(14); const id = groupID.slice(14);
const ancestorDiffBox = commentDiv.closest('.diff-file-box');
// on pages like conversation, there is no diff header
const diffHeader = ancestorDiffBox.find('.diff-file-header');
// offset is for scrolling
let offset = 30;
if (diffHeader[0]) {
offset += $('.diff-detail-box').outerHeight() + diffHeader.outerHeight();
}
$(`#show-outdated-${id}`).addClass('gt-hidden'); $(`#show-outdated-${id}`).addClass('gt-hidden');
$(`#code-comments-${id}`).removeClass('gt-hidden'); $(`#code-comments-${id}`).removeClass('gt-hidden');
$(`#code-preview-${id}`).removeClass('gt-hidden'); $(`#code-preview-${id}`).removeClass('gt-hidden');
$(`#hide-outdated-${id}`).removeClass('gt-hidden'); $(`#hide-outdated-${id}`).removeClass('gt-hidden');
// if the comment box is folded, expand it commentDiv[0].scrollIntoView();
if (ancestorDiffBox.attr('data-folded') && ancestorDiffBox.attr('data-folded') === 'true') {
setFileFolding(ancestorDiffBox[0], ancestorDiffBox.find('.fold-file')[0], false);
}
window.scrollTo({
top: commentDiv.offset().top - offset,
behavior: 'instant'
});
} }
} }
} }
@ -511,23 +491,12 @@ export function initRepoPullRequestReview() {
return; return;
} }
const $reviewBtn = $('.js-btn-review'); $('.js-btn-review').on('click', function (e) {
const $panel = $reviewBtn.parent().find('.review-box-panel');
const $closeBtn = $panel.find('.close');
const tippy = createTippy($reviewBtn[0], {
content: $panel[0],
placement: 'bottom',
trigger: 'click',
role: 'menu',
maxWidth: 'none',
interactive: true,
hideOnClick: true,
});
$closeBtn.on('click', (e) => {
e.preventDefault(); e.preventDefault();
tippy.hide(); toggleElem($(this).parent().find('.review-box-panel'));
}).parent().find('.review-box-panel .close').on('click', function (e) {
e.preventDefault();
hideElem($(this).closest('.review-box-panel'));
}); });
$(document).on('click', 'a.add-code-comment', async function (e) { $(document).on('click', 'a.add-code-comment', async function (e) {