mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-10 05:24:18 +09:00
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:
@@ -54,7 +54,7 @@ func TestCreateOrUpdateIssueNotificationsIgnored(t *testing.T) {
|
||||
// user 4 watches repo 1 and would be notified about issue 1
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
assert.NoError(t, repo_model.IgnoreRepo(t.Context(), user, repo))
|
||||
assert.NoError(t, repo_model.WatchIgnoreRepo(t.Context(), user, repo))
|
||||
|
||||
notified, err := activities_model.CreateOrUpdateIssueNotifications(t.Context(), 1, 0, 2, 0)
|
||||
assert.NoError(t, err)
|
||||
|
||||
+37
-3
@@ -74,6 +74,29 @@ func (w *Watch) IsIgnoring() bool {
|
||||
return w.Mode == WatchModeDont
|
||||
}
|
||||
|
||||
// IsWatching reports whether the watch counts the user as a watcher of the repository
|
||||
func (w *Watch) IsWatching() bool {
|
||||
return IsWatchMode(w.Mode)
|
||||
}
|
||||
|
||||
// IsWatchingAll reports whether every event is enabled, which is the "all activity" mode
|
||||
func (w *Watch) IsWatchingAll() bool {
|
||||
return w.PullRequests && w.Issues && w.Releases
|
||||
}
|
||||
|
||||
// SelectedMode returns the mode the user picked in the watch menu
|
||||
func (w *Watch) SelectedMode() string {
|
||||
switch {
|
||||
case w.IsIgnoring():
|
||||
return "ignore"
|
||||
case !IsWatchMode(w.Mode), !(w.PullRequests || w.Issues || w.Releases):
|
||||
return "participate" // also the default while there is no watch row
|
||||
case w.IsWatchingAll():
|
||||
return "all"
|
||||
}
|
||||
return "custom"
|
||||
}
|
||||
|
||||
// IsWatchMode Decodes watchability of WatchMode
|
||||
func IsWatchMode(mode WatchMode) bool {
|
||||
return mode != WatchModeNone && mode != WatchModeDont
|
||||
@@ -145,8 +168,8 @@ func WatchRepo(ctx context.Context, doer *user_model.User, repo *Repository, doW
|
||||
return watchRepoMode(ctx, watch, WatchModeNormal)
|
||||
}
|
||||
|
||||
// IgnoreRepo mutes the repository, so nothing about it reaches the user.
|
||||
func IgnoreRepo(ctx context.Context, doer *user_model.User, repo *Repository) error {
|
||||
// WatchIgnoreRepo mutes the repository (unwatch), so nothing about it reaches the user.
|
||||
func WatchIgnoreRepo(ctx context.Context, doer *user_model.User, repo *Repository) error {
|
||||
watch, err := GetWatch(ctx, doer.ID, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -160,6 +183,16 @@ type WatchOptions struct {
|
||||
Releases bool
|
||||
}
|
||||
|
||||
// WatchRepoWithOptions starts watching the repository and subscribes to the given events
|
||||
func WatchRepoWithOptions(ctx context.Context, doer *user_model.User, repo *Repository, opts WatchOptions) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if err := WatchRepo(ctx, doer, repo, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return SetWatchOptions(ctx, doer.ID, repo.ID, opts)
|
||||
})
|
||||
}
|
||||
|
||||
// SetWatchOptions updates the per-event options of a watch, callers must run WatchRepo first
|
||||
func SetWatchOptions(ctx context.Context, userID, repoID int64, opts WatchOptions) error {
|
||||
_, err := db.GetEngine(ctx).Where("user_id=? AND repo_id=?", userID, repoID).
|
||||
@@ -187,11 +220,12 @@ func GetUserWatches(ctx context.Context, userID int64, repoIDs []int64) (map[int
|
||||
return watchesByRepo, nil
|
||||
}
|
||||
|
||||
// GetWatchers returns all watchers of given repository.
|
||||
// GetWatchers returns all watchers of given repository, skipping those subscribed to no event.
|
||||
func GetWatchers(ctx context.Context, repoID int64) ([]*Watch, error) {
|
||||
watches := make([]*Watch, 0, 10)
|
||||
return watches, db.GetEngine(ctx).Where("`watch`.repo_id=?", repoID).
|
||||
And("`watch`.mode<>?", WatchModeDont).
|
||||
And(builder.Or(builder.Eq{"`watch`.pull_requests": true}, builder.Eq{"`watch`.issues": true}, builder.Eq{"`watch`.releases": true})).
|
||||
And("`user`.is_active=?", true).
|
||||
And("`user`.prohibit_login=?", false).
|
||||
Join("INNER", "`user`", "`user`.id = `watch`.user_id").
|
||||
|
||||
@@ -167,5 +167,14 @@ func TestWatchOptions(t *testing.T) {
|
||||
assert.NoError(t, repo_model.WatchRepo(t.Context(), user, repo, true))
|
||||
watch, err := repo_model.GetWatch(t.Context(), user.ID, repo.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, watch.PullRequests && watch.Issues && watch.Releases)
|
||||
assert.True(t, watch.IsWatchingAll())
|
||||
}
|
||||
|
||||
func TestWatchSelectedMode(t *testing.T) {
|
||||
// a user without a watch row gets the dummy record, whose flags are the column defaults
|
||||
assert.Equal(t, "participate", (&repo_model.Watch{Mode: repo_model.WatchModeNone, PullRequests: true, Issues: true, Releases: true}).SelectedMode())
|
||||
assert.Equal(t, "participate", (&repo_model.Watch{Mode: repo_model.WatchModeNormal}).SelectedMode())
|
||||
assert.Equal(t, "ignore", (&repo_model.Watch{Mode: repo_model.WatchModeDont}).SelectedMode())
|
||||
assert.Equal(t, "custom", (&repo_model.Watch{Mode: repo_model.WatchModeNormal, Issues: true}).SelectedMode())
|
||||
assert.Equal(t, "all", (&repo_model.Watch{Mode: repo_model.WatchModeAuto, PullRequests: true, Issues: true, Releases: true}).SelectedMode())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user