mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-05-25 11:22:16 +00:00
Direct avatar rendering (#13649)
* Direct avatar rendering This adds new template helpers for avatar rendering which output image elements with direct links to avatars which makes them cacheable by the browsers. This should be a major performance improvment for pages with many avatars. * fix avatars of other user's profile pages * fix top border on user avatar name * uncircle avatars * remove old incomplete avatar selector * use title attribute for name and add it back on blame * minor refactor * tweak comments * fix url path join and adjust test to new result * dedupe functions
This commit is contained in:
parent
0d35ef5b43
commit
9269a038a4
62 changed files with 435 additions and 340 deletions
|
@ -8,9 +8,13 @@ import (
|
|||
"crypto/md5"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
|
@ -20,6 +24,28 @@ type EmailHash struct {
|
|||
Email string `xorm:"UNIQUE NOT NULL"`
|
||||
}
|
||||
|
||||
// DefaultAvatarLink the default avatar link
|
||||
func DefaultAvatarLink() string {
|
||||
u, err := url.Parse(setting.AppSubURL)
|
||||
if err != nil {
|
||||
log.Error("GetUserByEmail: %v", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
u.Path = path.Join(u.Path, "/img/avatar_default.png")
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// DefaultAvatarSize is a sentinel value for the default avatar size, as
|
||||
// determined by the avatar-hosting service.
|
||||
const DefaultAvatarSize = -1
|
||||
|
||||
// HashEmail hashes email address to MD5 string.
|
||||
// https://en.gravatar.com/site/implement/hash/
|
||||
func HashEmail(email string) string {
|
||||
return base.EncodeMD5(strings.ToLower(strings.TrimSpace(email)))
|
||||
}
|
||||
|
||||
// GetEmailForHash converts a provided md5sum to the email
|
||||
func GetEmailForHash(md5Sum string) (string, error) {
|
||||
return cache.GetString("Avatar:"+md5Sum, func() (string, error) {
|
||||
|
@ -32,8 +58,24 @@ func GetEmailForHash(md5Sum string) (string, error) {
|
|||
})
|
||||
}
|
||||
|
||||
// AvatarLink returns an avatar link for a provided email
|
||||
func AvatarLink(email string) string {
|
||||
// LibravatarURL returns the URL for the given email. This function should only
|
||||
// be called if a federated avatar service is enabled.
|
||||
func LibravatarURL(email string) (*url.URL, error) {
|
||||
urlStr, err := setting.LibravatarService.FromEmail(email)
|
||||
if err != nil {
|
||||
log.Error("LibravatarService.FromEmail(email=%s): error %v", email, err)
|
||||
return nil, err
|
||||
}
|
||||
u, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
log.Error("Failed to parse libravatar url(%s): error %v", urlStr, err)
|
||||
return nil, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// HashedAvatarLink returns an avatar link for a provided email
|
||||
func HashedAvatarLink(email string) string {
|
||||
lowerEmail := strings.ToLower(strings.TrimSpace(email))
|
||||
sum := fmt.Sprintf("%x", md5.Sum([]byte(lowerEmail)))
|
||||
_, _ = cache.GetString("Avatar:"+sum, func() (string, error) {
|
||||
|
@ -57,3 +99,34 @@ func AvatarLink(email string) string {
|
|||
})
|
||||
return setting.AppSubURL + "/avatar/" + url.PathEscape(sum)
|
||||
}
|
||||
|
||||
// MakeFinalAvatarURL constructs the final avatar URL string
|
||||
func MakeFinalAvatarURL(u *url.URL, size int) string {
|
||||
vals := u.Query()
|
||||
vals.Set("d", "identicon")
|
||||
if size != DefaultAvatarSize {
|
||||
vals.Set("s", strconv.Itoa(size))
|
||||
}
|
||||
u.RawQuery = vals.Encode()
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// SizedAvatarLink returns a sized link to the avatar for the given email address.
|
||||
func SizedAvatarLink(email string, size int) string {
|
||||
var avatarURL *url.URL
|
||||
if setting.EnableFederatedAvatar && setting.LibravatarService != nil {
|
||||
// This is the slow path that would need to call LibravatarURL() which
|
||||
// does DNS lookups. Avoid it by issuing a redirect so we don't block
|
||||
// the template render with network requests.
|
||||
return HashedAvatarLink(email)
|
||||
} else if !setting.DisableGravatar {
|
||||
// copy GravatarSourceURL, because we will modify its Path.
|
||||
copyOfGravatarSourceURL := *setting.GravatarSourceURL
|
||||
avatarURL = ©OfGravatarSourceURL
|
||||
avatarURL.Path = path.Join(avatarURL.Path, HashEmail(email))
|
||||
} else {
|
||||
return DefaultAvatarLink()
|
||||
}
|
||||
|
||||
return MakeFinalAvatarURL(avatarURL, size)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue