mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-25 22:06:24 +02:00
Eliminate a few database queries on all issue and pull request pages by moving mention autocomplete data to async JSON endpoints fetched on-demand when the user types `@`. See https://github.com/go-gitea/gitea/pull/36739#issuecomment-3963184858 for the full table of affected pages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package mention
|
|
|
|
import (
|
|
"context"
|
|
|
|
"code.gitea.io/gitea/models/organization"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
)
|
|
|
|
// Mention is the JSON structure returned by mention autocomplete endpoints.
|
|
type Mention struct {
|
|
Key string `json:"key"`
|
|
Value string `json:"value"`
|
|
Name string `json:"name"`
|
|
FullName string `json:"fullname"`
|
|
Avatar string `json:"avatar"`
|
|
}
|
|
|
|
// Collector builds a deduplicated list of Mention entries.
|
|
type Collector struct {
|
|
seen map[string]bool
|
|
Result []Mention
|
|
}
|
|
|
|
// NewCollector creates a new Collector.
|
|
func NewCollector() *Collector {
|
|
return &Collector{seen: make(map[string]bool)}
|
|
}
|
|
|
|
// AddUsers adds user mentions, skipping duplicates.
|
|
func (c *Collector) AddUsers(ctx context.Context, users []*user_model.User) {
|
|
for _, u := range users {
|
|
if !c.seen[u.Name] {
|
|
c.seen[u.Name] = true
|
|
c.Result = append(c.Result, Mention{
|
|
Key: u.Name + " " + u.FullName,
|
|
Value: u.Name,
|
|
Name: u.Name,
|
|
FullName: u.FullName,
|
|
Avatar: u.AvatarLink(ctx),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// AddMentionableTeams loads and adds team mentions for the given owner (if it's an org).
|
|
func (c *Collector) AddMentionableTeams(ctx context.Context, doer, owner *user_model.User) error {
|
|
if doer == nil || !owner.IsOrganization() {
|
|
return nil
|
|
}
|
|
|
|
org := organization.OrgFromUser(owner)
|
|
isAdmin := doer.IsAdmin
|
|
if !isAdmin {
|
|
var err error
|
|
isAdmin, err = org.IsOwnedBy(ctx, doer.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var teams []*organization.Team
|
|
var err error
|
|
if isAdmin {
|
|
teams, err = org.LoadTeams(ctx)
|
|
} else {
|
|
teams, err = org.GetUserTeams(ctx, doer.ID)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, team := range teams {
|
|
key := owner.Name + "/" + team.Name
|
|
if !c.seen[key] {
|
|
c.seen[key] = true
|
|
c.Result = append(c.Result, Mention{
|
|
Key: key,
|
|
Value: key,
|
|
Name: key,
|
|
Avatar: owner.AvatarLink(ctx),
|
|
})
|
|
}
|
|
}
|
|
return nil
|
|
}
|