enhance: refine repo watching (#38835)

Follow-up to https://github.com/go-gitea/gitea/pull/37571.

"Participating and mentions" deleted the watch row, so choosing it
dropped you out of the watcher count. It is a watch like the others, so
it now keeps a row and simply subscribes to no events.

The dashboard feed ignored the per-event options, so a "Custom: issues"
watcher still got pull request activity there. It now gates on the same
options as mail and notifications. That also closes a gap where pull
request reviews bypassed the permission check.

Also, address
https://github.com/go-gitea/gitea/pull/37571#discussion_r3740487363 and
reword a UI text for clarity.

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-08-09 10:54:31 +00:00
committed by GitHub
co-authored by wxiaoguang
parent 76a81b24f9
commit ad6107ab88
14 changed files with 137 additions and 92 deletions
+25 -21
View File
@@ -1,11 +1,12 @@
{{$isIgnoring := and $.IsSigned $.Watch.IsIgnoring}}
{{$buttonText := ctx.Locale.Tr (Iif $isIgnoring "repo.ignoring" (Iif $.IsWatchingRepo "repo.watching" "repo.watch"))}}
{{$isIgnoring := and $.IsSigned $.RepoWatch.IsIgnoring}}
{{$buttonText := ctx.Locale.Tr (Iif $isIgnoring "repo.ignoring" (Iif $.RepoWatch.IsWatching "repo.watching" "repo.watch"))}}
{{$count := CountFmt .Repository.NumWatches}}
<div id="repo-header-watch" class="flex-text-block">
{{if $.IsSigned}}
{{$isAll := and $.IsWatchingRepo $.Watch.PullRequests $.Watch.Issues $.Watch.Releases}}
{{$isCustom := and $.IsWatchingRepo (not $isAll)}}
{{$isParticipating := not (or $.IsWatchingRepo $isIgnoring)}}
{{$mode := $.RepoWatch.SelectedMode}}
{{$isAll := eq $mode "all"}}
{{$isCustom := eq $mode "custom"}}
{{$isParticipating := eq $mode "participate"}}
<button class="ui dropdown custom compact small basic button" data-global-init="initRepoWatchMenu" aria-label="{{$buttonText}}">
{{svg (Iif $isIgnoring "octicon-eye-closed" "octicon-eye")}}
<span class="not-mobile" aria-hidden="true">{{$buttonText}}</span>
@@ -13,34 +14,37 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button>
<div class="tippy-target">
{{$participating := ctx.Locale.Tr "repo.watch.mode.participating"}}
<a class="item{{if $isParticipating}} active{{end}}" role="menuitem" aria-label="{{$participating}}"
data-fetch-method="post" data-fetch-url="{{$.RepoLink}}/action/unwatch" data-fetch-sync="$body #repo-header-watch"
{{$testParticipating := ctx.Locale.Tr "repo.watch.mode.participating"}}
<a class="item{{if $isParticipating}} active{{end}}" role="menuitem" aria-label="{{$testParticipating}}"
data-fetch-method="post" data-fetch-url="{{$.RepoLink}}/action/participate" data-fetch-sync="$body #repo-header-watch"
>
{{svg "octicon-check" 16 (Iif $isParticipating "" "tw-invisible")}}
<div>{{$participating}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.participating.desc"}}</div></div>
<div>{{$testParticipating}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.participating.desc"}}</div></div>
</a>
{{$all := ctx.Locale.Tr "repo.watch.mode.all"}}
<a class="item{{if $isAll}} active{{end}}" role="menuitem" aria-label="{{$all}}"
{{$textAll := ctx.Locale.Tr "repo.watch.mode.all"}}
<a class="item{{if $isAll}} active{{end}}" role="menuitem" aria-label="{{$textAll}}"
data-fetch-method="post" data-fetch-url="{{$.RepoLink}}/action/watch" data-fetch-sync="$body #repo-header-watch"
>
{{svg "octicon-check" 16 (Iif $isAll "" "tw-invisible")}}
<div>{{$all}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.all.desc"}}</div></div>
<div>{{$textAll}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.all.desc"}}</div></div>
</a>
{{$ignore := ctx.Locale.Tr "repo.watch.mode.ignore"}}
<a class="item{{if $.Watch.IsIgnoring}} active{{end}}" role="menuitem" aria-label="{{$ignore}}"
{{$textIgnore := ctx.Locale.Tr "repo.watch.mode.ignore"}}
<a class="item{{if $isIgnoring}} active{{end}}" role="menuitem" aria-label="{{$textIgnore}}"
data-fetch-method="post" data-fetch-url="{{$.RepoLink}}/action/ignore" data-fetch-sync="$body #repo-header-watch"
>
{{svg "octicon-check" 16 (Iif $.Watch.IsIgnoring "" "tw-invisible")}}
<div>{{$ignore}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.ignore.desc"}}</div></div>
{{svg "octicon-check" 16 (Iif $isIgnoring "" "tw-invisible")}}
<div>{{$textIgnore}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.ignore.desc"}}</div></div>
</a>
{{$custom := ctx.Locale.Tr "repo.watch.mode.custom"}}
<a class="item{{if $isCustom}} active{{end}}" role="menuitem" aria-label="{{$custom}}"
data-global-click="onRepoWatchOptionsClick" data-url="{{$.RepoLink}}/action/watch/options"
data-issues="{{$.Watch.Issues}}" data-pull-requests="{{$.Watch.PullRequests}}" data-releases="{{$.Watch.Releases}}"
{{$textCustom := ctx.Locale.Tr "repo.watch.mode.custom"}}
<a class="item {{if $isCustom}}active{{end}} show-modal" role="menuitem" aria-label="{{$textCustom}}"
data-modal="#repo-watch-options-modal"
data-modal-form.url="{{$.RepoLink}}/action/watch/options"
data-modal-issues="{{$.RepoWatch.Issues}}"
data-modal-pull_requests="{{$.RepoWatch.PullRequests}}"
data-modal-releases="{{$.RepoWatch.Releases}}"
>
{{svg "octicon-check" 16 (Iif $isCustom "" "tw-invisible")}}
<div>{{$custom}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.custom.desc"}}</div></div>
<div>{{$textCustom}}<div class="tw-text-12 tw-text-text-light-2">{{ctx.Locale.Tr "repo.watch.mode.custom.desc"}}</div></div>
</a>
</div>
{{else}}
+13 -6
View File
@@ -2,13 +2,20 @@
<div class="header">{{ctx.Locale.Tr "notifications"}}</div>
<form class="ui form form-fetch-action" method="post">
<div class="content">
{{range $name := StringUtils.Split "issues,pull_requests,releases" ","}}
<div class="field">
<div class="ui checkbox">
<input name="{{$name}}" type="checkbox"><label>{{ctx.Locale.Tr (printf "repo.watch.options.%s" $name)}}</label>
</div>
<div class="flex-relaxed-list tw-gap-4">
<div class="ui checkbox">
<input name="issues" type="checkbox">
<label>{{ctx.Locale.Tr "repo.watch.options.issues"}}</label>
</div>
{{end}}
<div class="ui checkbox">
<input name="pull_requests" type="checkbox">
<label>{{ctx.Locale.Tr "repo.watch.options.pull_requests"}}</label>
</div>
<div class="ui checkbox">
<input name="releases" type="checkbox">
<label>{{ctx.Locale.Tr "repo.watch.options.releases"}}</label>
</div>
</div>
</div>
{{template "base/modal_actions_confirm" dict "ModalButtonTypes" "confirm"}}
</form>
+6 -3
View File
@@ -57,9 +57,12 @@
</a>
{{$watch := and $.Watches (index $.Watches .ID)}}
{{if $watch}}
<button class="btn flex-text-inline" data-global-click="onRepoWatchOptionsClick"
data-url="{{.Link}}/action/watch/options"
data-issues="{{$watch.Issues}}" data-pull-requests="{{$watch.PullRequests}}" data-releases="{{$watch.Releases}}"
<button class="btn flex-text-inline show-modal"
data-modal="#repo-watch-options-modal"
data-modal-form.url="{{.Link}}/action/watch/options"
data-modal-issues="{{$watch.Issues}}"
data-modal-pull_requests="{{$watch.PullRequests}}"
data-modal-releases="{{$watch.Releases}}"
data-tooltip-content="{{ctx.Locale.Tr "notifications"}}"
>{{svg "octicon-gear" 16}}</button>
{{end}}