mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-26 06:16:56 +09:00
feat: add release reactions and a GitHub-like reaction bar (#38415)
Adds emoji reactions to releases and moves the reaction picker of issues, comments and releases into a GitHub-like reaction bar. - Releases omit 👎 or 😕 - Drafts and tags can't be reacted to - Moved menu to tippy - Added keyboard navigation Fixes: https://github.com/go-gitea/gitea/issues/34268 Fixes: https://github.com/go-gitea/gitea/issues/16676 Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
42 files changed
+508
-313
No files matched your search
@@ -0,0 +1,33 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package release
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
)
|
||||
|
||||
func AllowedReleaseReactions() []string {
|
||||
return setting.UI.ReleaseReactions
|
||||
}
|
||||
|
||||
func CreateReleaseReaction(ctx context.Context, doer *user_model.User, rel *repo_model.Release, content string) (*issues_model.Reaction, error) {
|
||||
if err := rel.LoadRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user_model.IsUserBlockedBy(ctx, doer, rel.PublisherID, rel.Repo.OwnerID) {
|
||||
return nil, user_model.ErrBlockedUser
|
||||
}
|
||||
|
||||
return issues_model.CreateReaction(ctx, setting.UI.ReleaseReactionsLookup, &issues_model.ReactionOptions{
|
||||
Type: content,
|
||||
DoerID: doer.ID,
|
||||
ReleaseID: rel.ID,
|
||||
})
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"gitea.dev/models/db"
|
||||
git_model "gitea.dev/models/git"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/container"
|
||||
@@ -421,6 +422,10 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
|
||||
return fmt.Errorf("DeleteAttachments: %w", err)
|
||||
}
|
||||
|
||||
if _, err := db.DeleteByBean(ctx, &issues_model.Reaction{ReleaseID: rel.ID}); err != nil {
|
||||
return fmt.Errorf("DeleteReleaseByID: %w", err)
|
||||
}
|
||||
|
||||
for i := range rel.Attachments {
|
||||
attachment := rel.Attachments[i]
|
||||
if err := storage.Attachments.Delete(attachment.RelativePath()); err != nil {
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dev/models/db"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
@@ -407,6 +409,25 @@ func TestCreateNewTag(t *testing.T) {
|
||||
"v2.0 is released \n\n BUGFIX: .... \n\n 123"))
|
||||
}
|
||||
|
||||
func TestCreateReleaseReaction(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 1})
|
||||
|
||||
assert.Equal(t, []string{"+1", "laugh", "hooray", "heart", "rocket", "eyes"}, AllowedReleaseReactions())
|
||||
|
||||
_, err := CreateReleaseReaction(t.Context(), user, release, "heart")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, DeleteReleaseByID(t.Context(), repo, release, user, false))
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Reaction{ReleaseID: release.ID})
|
||||
|
||||
assert.NoError(t, db.Insert(t.Context(), &user_model.Blocking{BlockerID: repo.OwnerID, BlockeeID: user.ID}))
|
||||
_, err = CreateReleaseReaction(t.Context(), user, release, "heart")
|
||||
assert.ErrorIs(t, err, user_model.ErrBlockedUser)
|
||||
}
|
||||
|
||||
func TestRelease_DatedByTargetCommit(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
Reference in new issue
Block a user