Fix frontpage avatars (#13853)

The frontpage uses a rather strange method to obtain the commit's avatar
which I've overlooked earlier. I don't exactly understand how it works
but this change fixes the wrong default avatars by using the function
that was in previous use.

Also introduced a few constants for size an size increase factor.

Fixes: https://github.com/go-gitea/gitea/issues/13844
This commit is contained in:
silverwind 2020-12-09 01:12:15 +01:00 committed by GitHub
parent 658e90a114
commit c05701dd7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 78 additions and 65 deletions

View file

@ -40,6 +40,12 @@ func DefaultAvatarLink() string {
// determined by the avatar-hosting service. // determined by the avatar-hosting service.
const DefaultAvatarSize = -1 const DefaultAvatarSize = -1
// DefaultAvatarPixelSize is the default size in pixels of a rendered avatar
const DefaultAvatarPixelSize = 28
// AvatarRenderedSizeFactor is the factor by which the default size is increased for finer rendering
const AvatarRenderedSizeFactor = 2
// HashEmail hashes email address to MD5 string. // HashEmail hashes email address to MD5 string.
// https://en.gravatar.com/site/implement/hash/ // https://en.gravatar.com/site/implement/hash/
func HashEmail(email string) string { func HashEmail(email string) string {

View file

@ -118,12 +118,14 @@ func (pc *PushCommits) AvatarLink(email string) string {
return avatar return avatar
} }
size := models.DefaultAvatarPixelSize * models.AvatarRenderedSizeFactor
u, ok := pc.emailUsers[email] u, ok := pc.emailUsers[email]
if !ok { if !ok {
var err error var err error
u, err = models.GetUserByEmail(email) u, err = models.GetUserByEmail(email)
if err != nil { if err != nil {
pc.avatars[email] = models.HashedAvatarLink(email) pc.avatars[email] = models.SizedAvatarLink(email, size)
if !models.IsErrUserNotExist(err) { if !models.IsErrUserNotExist(err) {
log.Error("GetUserByEmail: %v", err) log.Error("GetUserByEmail: %v", err)
return "" return ""
@ -133,7 +135,7 @@ func (pc *PushCommits) AvatarLink(email string) string {
} }
} }
if u != nil { if u != nil {
pc.avatars[email] = u.RelAvatarLink() pc.avatars[email] = u.RealSizedAvatarLink(size)
} }
return pc.avatars[email] return pc.avatars[email]

View file

@ -112,11 +112,13 @@ func TestPushCommits_AvatarLink(t *testing.T) {
pushCommits.Len = len(pushCommits.Commits) pushCommits.Len = len(pushCommits.Commits)
assert.Equal(t, assert.Equal(t,
"/user/avatar/user2/-1", "https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon&s=56",
pushCommits.AvatarLink("user2@example.com")) pushCommits.AvatarLink("user2@example.com"))
assert.Equal(t, assert.Equal(t,
"/avatar/"+fmt.Sprintf("%x", md5.Sum([]byte("nonexistent@example.com"))), "https://secure.gravatar.com/avatar/"+
fmt.Sprintf("%x", md5.Sum([]byte("nonexistent@example.com")))+
"?d=identicon&s=56",
pushCommits.AvatarLink("nonexistent@example.com")) pushCommits.AvatarLink("nonexistent@example.com"))
} }

View file

@ -340,6 +340,7 @@ func NewFuncMap() []template.FuncMap {
}, },
"svg": SVG, "svg": SVG,
"avatar": Avatar, "avatar": Avatar,
"avatarHTML": AvatarHTML,
"avatarByEmail": AvatarByEmail, "avatarByEmail": AvatarByEmail,
"repoAvatar": RepoAvatar, "repoAvatar": RepoAvatar,
"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML { "SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML {
@ -519,7 +520,8 @@ func parseOthers(defaultSize int, defaultClass string, others ...interface{}) (i
return size, class return size, class
} }
func avatarHTML(src string, size int, class string, name string) template.HTML { // AvatarHTML creates the HTML for an avatar
func AvatarHTML(src string, size int, class string, name string) template.HTML {
sizeStr := fmt.Sprintf(`%d`, size) sizeStr := fmt.Sprintf(`%d`, size)
if name == "" { if name == "" {
@ -548,33 +550,33 @@ func SVG(icon string, others ...interface{}) template.HTML {
// Avatar renders user avatars. args: user, size (int), class (string) // Avatar renders user avatars. args: user, size (int), class (string)
func Avatar(user *models.User, others ...interface{}) template.HTML { func Avatar(user *models.User, others ...interface{}) template.HTML {
size, class := parseOthers(28, "ui avatar image", others...) size, class := parseOthers(models.DefaultAvatarPixelSize, "ui avatar image", others...)
src := user.RealSizedAvatarLink(size * 2) // request double size for finer rendering src := user.RealSizedAvatarLink(size * models.AvatarRenderedSizeFactor)
if src != "" { if src != "" {
return avatarHTML(src, size, class, user.DisplayName()) return AvatarHTML(src, size, class, user.DisplayName())
} }
return template.HTML("") return template.HTML("")
} }
// RepoAvatar renders repo avatars. args: repo, size(int), class (string) // RepoAvatar renders repo avatars. args: repo, size(int), class (string)
func RepoAvatar(repo *models.Repository, others ...interface{}) template.HTML { func RepoAvatar(repo *models.Repository, others ...interface{}) template.HTML {
size, class := parseOthers(28, "ui avatar image", others...) size, class := parseOthers(models.DefaultAvatarPixelSize, "ui avatar image", others...)
src := repo.RelAvatarLink() src := repo.RelAvatarLink()
if src != "" { if src != "" {
return avatarHTML(src, size, class, repo.FullName()) return AvatarHTML(src, size, class, repo.FullName())
} }
return template.HTML("") return template.HTML("")
} }
// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string) // AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string)
func AvatarByEmail(email string, name string, others ...interface{}) template.HTML { func AvatarByEmail(email string, name string, others ...interface{}) template.HTML {
size, class := parseOthers(28, "ui avatar image", others...) size, class := parseOthers(models.DefaultAvatarPixelSize, "ui avatar image", others...)
src := models.SizedAvatarLink(email, size*2) // request double size for finer rendering src := models.SizedAvatarLink(email, size*models.AvatarRenderedSizeFactor)
if src != "" { if src != "" {
return avatarHTML(src, size, class, name) return AvatarHTML(src, size, class, name)
} }
return template.HTML("") return template.HTML("")

View file

@ -11,23 +11,23 @@
{{end}} {{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.ico"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/dingtalk.ico">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/msteams.png">
{{else if eq .HookType "feishu"}} {{else if eq .HookType "feishu"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/feishu.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/feishu.png">
{{else if eq .HookType "matrix"}} {{else if eq .HookType "matrix"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/matrix.svg"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/matrix.svg">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -10,23 +10,23 @@
{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}} {{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/dingtalk.png">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/msteams.png">
{{else if eq .HookType "feishu"}} {{else if eq .HookType "feishu"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/feishu.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/feishu.png">
{{else if eq .HookType "matrix"}} {{else if eq .HookType "matrix"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/matrix.svg"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/matrix.svg">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -90,7 +90,7 @@
<p class="text grey"> <p class="text grey">
{{ if gt .Publisher.ID 0 }} {{ if gt .Publisher.ID 0 }}
<span class="author"> <span class="author">
{{avatar .Publisher 28 "img-10"}} {{avatar .Publisher 20}}
<a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a> <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a>
</span> </span>
{{ end }} {{ end }}
@ -117,7 +117,7 @@
{{if .OriginalAuthor}} {{if .OriginalAuthor}}
{{svg "octicon-mark-github" 16 "mr-2"}}{{.OriginalAuthor}} {{svg "octicon-mark-github" 16 "mr-2"}}{{.OriginalAuthor}}
{{else if .Publisher}} {{else if .Publisher}}
{{avatar .Publisher 28 "img-10"}} {{avatar .Publisher 20}}
<a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.GetDisplayName}}</a> <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.GetDisplayName}}</a>
{{else}} {{else}}
Ghost Ghost

View file

@ -6,31 +6,31 @@
<div class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_webhook"}}</div> <div class="ui blue tiny button">{{.i18n.Tr "repo.settings.add_webhook"}}</div>
<div class="menu"> <div class="menu">
<a class="item" href="{{.BaseLink}}/gitea/new"> <a class="item" href="{{.BaseLink}}/gitea/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/gitea-sm.png">Gitea <img width="20" height="20" src="{{StaticUrlPrefix}}/img/gitea-sm.png">Gitea
</a> </a>
<a class="item" href="{{.BaseLink}}/gogs/new"> <a class="item" href="{{.BaseLink}}/gogs/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/gogs.ico">Gogs <img width="20" height="20" src="{{StaticUrlPrefix}}/img/gogs.ico">Gogs
</a> </a>
<a class="item" href="{{.BaseLink}}/slack/new"> <a class="item" href="{{.BaseLink}}/slack/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/slack.png">Slack <img width="20" height="20" src="{{StaticUrlPrefix}}/img/slack.png">Slack
</a> </a>
<a class="item" href="{{.BaseLink}}/discord/new"> <a class="item" href="{{.BaseLink}}/discord/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/discord.png">Discord <img width="20" height="20" src="{{StaticUrlPrefix}}/img/discord.png">Discord
</a> </a>
<a class="item" href="{{.BaseLink}}/dingtalk/new"> <a class="item" href="{{.BaseLink}}/dingtalk/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/dingtalk.ico">Dingtalk <img width="20" height="20" src="{{StaticUrlPrefix}}/img/dingtalk.ico">Dingtalk
</a> </a>
<a class="item" href="{{.BaseLink}}/telegram/new"> <a class="item" href="{{.BaseLink}}/telegram/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/telegram.png">Telegram <img width="20" height="20" src="{{StaticUrlPrefix}}/img/telegram.png">Telegram
</a> </a>
<a class="item" href="{{.BaseLink}}/msteams/new"> <a class="item" href="{{.BaseLink}}/msteams/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/msteams.png">Microsoft Teams <img width="20" height="20" src="{{StaticUrlPrefix}}/img/msteams.png">Microsoft Teams
</a> </a>
<a class="item" href="{{.BaseLink}}/feishu/new"> <a class="item" href="{{.BaseLink}}/feishu/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/feishu.png">Feishu <img width="20" height="20" src="{{StaticUrlPrefix}}/img/feishu.png">Feishu
</a> </a>
<a class="item" href="{{.BaseLink}}/matrix/new"> <a class="item" href="{{.BaseLink}}/matrix/new">
<img class="img-10" src="{{StaticUrlPrefix}}/img/matrix.svg">Matrix <img width="20" height="20" src="{{StaticUrlPrefix}}/img/matrix.svg">Matrix
</a> </a>
</div> </div>
</div> </div>

View file

@ -8,23 +8,23 @@
{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}} {{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}
<div class="ui right"> <div class="ui right">
{{if eq .HookType "gitea"}} {{if eq .HookType "gitea"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gitea-sm.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gitea-sm.png">
{{else if eq .HookType "gogs"}} {{else if eq .HookType "gogs"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/gogs.ico"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/gogs.ico">
{{else if eq .HookType "slack"}} {{else if eq .HookType "slack"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/slack.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/slack.png">
{{else if eq .HookType "discord"}} {{else if eq .HookType "discord"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/discord.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/discord.png">
{{else if eq .HookType "dingtalk"}} {{else if eq .HookType "dingtalk"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/dingtalk.ico"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/dingtalk.ico">
{{else if eq .HookType "telegram"}} {{else if eq .HookType "telegram"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/telegram.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/telegram.png">
{{else if eq .HookType "msteams"}} {{else if eq .HookType "msteams"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/msteams.png">
{{else if eq .HookType "feishu"}} {{else if eq .HookType "feishu"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/feishu.png"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/feishu.png">
{{else if eq .HookType "matrix"}} {{else if eq .HookType "matrix"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/matrix.svg"> <img width="26" height="26" src="{{StaticUrlPrefix}}/img/matrix.svg">
{{end}} {{end}}
</div> </div>
</h4> </h4>

View file

@ -3,7 +3,7 @@
<tr class="commit-list"> <tr class="commit-list">
<th colspan="2"> <th colspan="2">
{{if .LatestCommitUser}} {{if .LatestCommitUser}}
{{avatar .LatestCommitUser 28 "img-12"}} {{avatar .LatestCommitUser 24}}
{{if .LatestCommitUser.FullName}} {{if .LatestCommitUser.FullName}}
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a> <a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
{{else}} {{else}}
@ -11,7 +11,7 @@
{{end}} {{end}}
{{else}} {{else}}
{{if .LatestCommit.Author}} {{if .LatestCommit.Author}}
{{avatarByEmail .LatestCommit.Author.Email .LatestCommit.Author.Name 28 "img-12"}} {{avatarByEmail .LatestCommit.Author.Email .LatestCommit.Author.Name 24}}
<strong>{{.LatestCommit.Author.Name}}</strong> <strong>{{.LatestCommit.Author.Name}}</strong>
{{end}} {{end}}
{{end}} {{end}}

View file

@ -85,7 +85,7 @@
{{range $push.Commits}} {{range $push.Commits}}
{{ $commitLink := printf "%s/commit/%s" $repoLink .Sha1}} {{ $commitLink := printf "%s/commit/%s" $repoLink .Sha1}}
<li> <li>
{{avatarByEmail .AuthorEmail .AuthorName 28 "img-8 mr-2"}} {{avatarHTML ($push.AvatarLink .AuthorEmail) 16 "mr-2" .AuthorName}}
<a class="commit-id mr-2" href="{{$commitLink}}">{{ShortSha .Sha1}}</a> <a class="commit-id mr-2" href="{{$commitLink}}">{{ShortSha .Sha1}}</a>
<span class="text truncate light grey"> <span class="text truncate light grey">
{{RenderCommitMessage .Message $repoLink $.ComposeMetas}} {{RenderCommitMessage .Message $repoLink $.ComposeMetas}}

View file

@ -312,6 +312,12 @@ a.muted:hover,
font-weight: normal; font-weight: normal;
} }
/* fix misaligned images in webhook dropdown */
.ui.dropdown .menu > .item > img {
margin-top: -.25rem;
margin-bottom: -.25rem;
}
.ui.selection.dropdown .menu > .item { .ui.selection.dropdown .menu > .item {
border-color: var(--color-secondary); border-color: var(--color-secondary);
} }
@ -1101,16 +1107,6 @@ footer {
text-align: center; text-align: center;
} }
.generate-img(16);
.generate-img(@n, @i: 1) when (@i =< @n) {
.img-@{i} {
width: (2px * @i) !important;
height: (2px * @i) !important;
}
.generate-img(@n, (@i + 1));
}
// Conditional display // Conditional display
@media @mediaMdAndUp { @media @mediaMdAndUp {
.mobile-only, .mobile-only,
@ -1660,6 +1656,11 @@ a.ui.basic.label:hover {
visibility: hidden; visibility: hidden;
} }
/* prevent stacking context issue on webhook dropdown */
.ui.segment {
position: static;
}
.ui.segment, .ui.segment,
.ui.segments, .ui.segments,
.ui.attached.segment { .ui.attached.segment {

View file

@ -22,7 +22,7 @@
} }
.full-screen-width { width: 100vw !important; } .full-screen-width { width: 100vw !important; }
.full-screen-height { height: 100vw !important; } .full-screen-height { height: 100vh !important; }
.rounded { border-radius: var(--border-radius) !important; } .rounded { border-radius: var(--border-radius) !important; }
.rounded-top { border-radius: var(--border-radius) var(--border-radius) 0 0 !important; } .rounded-top { border-radius: var(--border-radius) var(--border-radius) 0 0 !important; }