diff --git a/models/action.go b/models/action.go
index f4d163afa..ca186033a 100644
--- a/models/action.go
+++ b/models/action.go
@@ -140,12 +140,6 @@ func (a *Action) GetDisplayNameTitle() string {
return a.GetActFullName()
}
-// GetActAvatar the action's user's avatar link
-func (a *Action) GetActAvatar() string {
- a.loadActUser()
- return a.ActUser.RelAvatarLink()
-}
-
// GetRepoUserName returns the name of the action repository owner.
func (a *Action) GetRepoUserName() string {
a.loadRepo()
diff --git a/models/avatar.go b/models/avatar.go
index c9ba2961e..ac260fbd9 100644
--- a/models/avatar.go
+++ b/models/avatar.go
@@ -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)
+}
diff --git a/models/avatar_test.go b/models/avatar_test.go
new file mode 100644
index 000000000..89540705a
--- /dev/null
+++ b/models/avatar_test.go
@@ -0,0 +1,52 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+ "net/url"
+ "testing"
+
+ "code.gitea.io/gitea/modules/setting"
+
+ "github.com/stretchr/testify/assert"
+)
+
+const gravatarSource = "https://secure.gravatar.com/avatar/"
+
+func disableGravatar() {
+ setting.EnableFederatedAvatar = false
+ setting.LibravatarService = nil
+ setting.DisableGravatar = true
+}
+
+func enableGravatar(t *testing.T) {
+ setting.DisableGravatar = false
+ var err error
+ setting.GravatarSourceURL, err = url.Parse(gravatarSource)
+ assert.NoError(t, err)
+}
+
+func TestHashEmail(t *testing.T) {
+ assert.Equal(t,
+ "d41d8cd98f00b204e9800998ecf8427e",
+ HashEmail(""),
+ )
+ assert.Equal(t,
+ "353cbad9b58e69c96154ad99f92bedc7",
+ HashEmail("gitea@example.com"),
+ )
+}
+
+func TestSizedAvatarLink(t *testing.T) {
+ disableGravatar()
+ assert.Equal(t, "/suburl/img/avatar_default.png",
+ SizedAvatarLink("gitea@example.com", 100))
+
+ enableGravatar(t)
+ assert.Equal(t,
+ "https://secure.gravatar.com/avatar/353cbad9b58e69c96154ad99f92bedc7?d=identicon&s=100",
+ SizedAvatarLink("gitea@example.com", 100),
+ )
+}
diff --git a/models/user_avatar.go b/models/user_avatar.go
index 2f9db5c2e..50c1c99c5 100644
--- a/models/user_avatar.go
+++ b/models/user_avatar.go
@@ -13,7 +13,6 @@ import (
"strings"
"code.gitea.io/gitea/modules/avatar"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
@@ -41,7 +40,7 @@ func (u *User) generateRandomAvatar(e Engine) error {
}
if u.Avatar == "" {
- u.Avatar = base.HashEmail(u.AvatarEmail)
+ u.Avatar = HashEmail(u.AvatarEmail)
}
if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
@@ -76,13 +75,13 @@ func (u *User) SizedRelAvatarLink(size int) string {
//
func (u *User) RealSizedAvatarLink(size int) string {
if u.ID == -1 {
- return base.DefaultAvatarLink()
+ return DefaultAvatarLink()
}
switch {
case u.UseCustomAvatar:
if u.Avatar == "" {
- return base.DefaultAvatarLink()
+ return DefaultAvatarLink()
}
return setting.AppSubURL + "/avatars/" + u.Avatar
case setting.DisableGravatar, setting.OfflineMode:
@@ -94,14 +93,14 @@ func (u *User) RealSizedAvatarLink(size int) string {
return setting.AppSubURL + "/avatars/" + u.Avatar
}
- return base.SizedAvatarLink(u.AvatarEmail, size)
+ return SizedAvatarLink(u.AvatarEmail, size)
}
// RelAvatarLink returns a relative link to the user's avatar. The link
// may either be a sub-URL to this site, or a full URL to an external avatar
// service.
func (u *User) RelAvatarLink() string {
- return u.SizedRelAvatarLink(base.DefaultAvatarSize)
+ return u.SizedRelAvatarLink(DefaultAvatarSize)
}
// AvatarLink returns user avatar absolute link.
diff --git a/modules/auth/sso/sspi_windows.go b/modules/auth/sso/sspi_windows.go
index 00f15d97b..62013737c 100644
--- a/modules/auth/sso/sspi_windows.go
+++ b/modules/auth/sso/sspi_windows.go
@@ -168,7 +168,7 @@ func (s *SSPI) newUser(ctx *macaron.Context, username string, cfg *models.SSPICo
IsActive: cfg.AutoActivateUsers,
Language: cfg.DefaultLanguage,
UseCustomAvatar: true,
- Avatar: base.DefaultAvatarLink(),
+ Avatar: models.DefaultAvatarLink(),
EmailNotificationsPreference: models.EmailNotificationsDisabled,
}
if err := models.CreateUser(user); err != nil {
diff --git a/modules/base/tool.go b/modules/base/tool.go
index a21fd9b0f..2cc09fb25 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -12,9 +12,7 @@ import (
"encoding/hex"
"fmt"
"net/http"
- "net/url"
"os"
- "path"
"path/filepath"
"runtime"
"strconv"
@@ -134,93 +132,6 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string
return code
}
-// HashEmail hashes email address to MD5 string.
-// https://en.gravatar.com/site/implement/hash/
-func HashEmail(email string) string {
- return EncodeMD5(strings.ToLower(strings.TrimSpace(email)))
-}
-
-// DefaultAvatarLink the default avatar link
-func DefaultAvatarLink() string {
- return setting.AppSubURL + "/img/avatar_default.png"
-}
-
-// DefaultAvatarSize is a sentinel value for the default avatar size, as
-// determined by the avatar-hosting service.
-const DefaultAvatarSize = -1
-
-// 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
-}
-
-// 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 {
- var err error
- avatarURL, err = libravatarURL(email)
- if err != nil {
- return DefaultAvatarLink()
- }
- } 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()
- }
-
- vals := avatarURL.Query()
- vals.Set("d", "identicon")
- if size != DefaultAvatarSize {
- vals.Set("s", strconv.Itoa(size))
- }
- avatarURL.RawQuery = vals.Encode()
- return avatarURL.String()
-}
-
-// SizedAvatarLinkWithDomain returns a sized link to the avatar for the given email
-// address.
-func SizedAvatarLinkWithDomain(email string, size int) string {
- var avatarURL *url.URL
- if setting.EnableFederatedAvatar && setting.LibravatarService != nil {
- var err error
- avatarURL, err = libravatarURL(email)
- if err != nil {
- return DefaultAvatarLink()
- }
- } 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()
- }
-
- vals := avatarURL.Query()
- vals.Set("d", "identicon")
- if size != DefaultAvatarSize {
- vals.Set("s", strconv.Itoa(size))
- }
- avatarURL.RawQuery = vals.Encode()
- return avatarURL.String()
-}
-
// FileSize calculates the file size and generate user-friendly string.
func FileSize(s int64) string {
return humanize.IBytes(uint64(s))
diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go
index f765fd0db..0c5bd6657 100644
--- a/modules/base/tool_test.go
+++ b/modules/base/tool_test.go
@@ -5,11 +5,8 @@
package base
import (
- "net/url"
"testing"
- "code.gitea.io/gitea/modules/setting"
-
"github.com/stretchr/testify/assert"
)
@@ -56,44 +53,6 @@ func TestBasicAuthEncode(t *testing.T) {
// TODO: Test VerifyTimeLimitCode()
// TODO: Test CreateTimeLimitCode()
-func TestHashEmail(t *testing.T) {
- assert.Equal(t,
- "d41d8cd98f00b204e9800998ecf8427e",
- HashEmail(""),
- )
- assert.Equal(t,
- "353cbad9b58e69c96154ad99f92bedc7",
- HashEmail("gitea@example.com"),
- )
-}
-
-const gravatarSource = "https://secure.gravatar.com/avatar/"
-
-func disableGravatar() {
- setting.EnableFederatedAvatar = false
- setting.LibravatarService = nil
- setting.DisableGravatar = true
-}
-
-func enableGravatar(t *testing.T) {
- setting.DisableGravatar = false
- var err error
- setting.GravatarSourceURL, err = url.Parse(gravatarSource)
- assert.NoError(t, err)
-}
-
-func TestSizedAvatarLink(t *testing.T) {
- disableGravatar()
- assert.Equal(t, "/img/avatar_default.png",
- SizedAvatarLink("gitea@example.com", 100))
-
- enableGravatar(t)
- assert.Equal(t,
- "https://secure.gravatar.com/avatar/353cbad9b58e69c96154ad99f92bedc7?d=identicon&s=100",
- SizedAvatarLink("gitea@example.com", 100),
- )
-}
-
func TestFileSize(t *testing.T) {
var size int64 = 512
assert.Equal(t, "512 B", FileSize(size))
diff --git a/modules/repository/commits.go b/modules/repository/commits.go
index e02f3d11c..fd8b8d927 100644
--- a/modules/repository/commits.go
+++ b/modules/repository/commits.go
@@ -123,7 +123,7 @@ func (pc *PushCommits) AvatarLink(email string) string {
var err error
u, err = models.GetUserByEmail(email)
if err != nil {
- pc.avatars[email] = models.AvatarLink(email)
+ pc.avatars[email] = models.HashedAvatarLink(email)
if !models.IsErrUserNotExist(err) {
log.Error("GetUserByEmail: %v", err)
return ""
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 8b9639752..5af1addb6 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -88,7 +88,6 @@ func NewFuncMap() []template.FuncMap {
"AllowedReactions": func() []string {
return setting.UI.Reactions
},
- "AvatarLink": models.AvatarLink,
"Safe": Safe,
"SafeJS": SafeJS,
"Str2html": Str2html,
@@ -339,7 +338,9 @@ func NewFuncMap() []template.FuncMap {
}
return false
},
- "svg": SVG,
+ "svg": SVG,
+ "avatar": Avatar,
+ "avatarByEmail": AvatarByEmail,
"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML {
// if needed
if len(normSort) == 0 || len(urlSort) == 0 {
@@ -499,18 +500,38 @@ func NewTextFuncMap() []texttmpl.FuncMap {
var widthRe = regexp.MustCompile(`width="[0-9]+?"`)
var heightRe = regexp.MustCompile(`height="[0-9]+?"`)
-// SVG render icons - arguments icon name (string), size (int), class (string)
-func SVG(icon string, others ...interface{}) template.HTML {
- size := 16
+func parseOthers(defaultSize int, defaultClass string, others ...interface{}) (int, string) {
+ size := defaultSize
if len(others) > 0 && others[0].(int) != 0 {
size = others[0].(int)
}
- class := ""
+ class := defaultClass
if len(others) > 1 && others[1].(string) != "" {
- class = others[1].(string)
+ if defaultClass == "" {
+ class = others[1].(string)
+ } else {
+ class = defaultClass + " " + others[1].(string)
+ }
}
+ return size, class
+}
+
+func avatarHTML(src string, size int, class string, name string) template.HTML {
+ sizeStr := fmt.Sprintf(`%d`, size)
+
+ if name == "" {
+ name = "avatar"
+ }
+
+ return template.HTML(``)
+}
+
+// SVG render icons - arguments icon name (string), size (int), class (string)
+func SVG(icon string, others ...interface{}) template.HTML {
+ size, class := parseOthers(16, "", others...)
+
if svgStr, ok := svg.SVGs[icon]; ok {
if size != 16 {
svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size))
@@ -524,6 +545,38 @@ func SVG(icon string, others ...interface{}) template.HTML {
return template.HTML("")
}
+// Avatar renders user and repo avatars. args: user/repo, size (int), class (string)
+func Avatar(item interface{}, others ...interface{}) template.HTML {
+ size, class := parseOthers(28, "ui avatar image", others...)
+ if user, ok := item.(*models.User); ok {
+ src := user.RealSizedAvatarLink(size * 2) // request double size for finer rendering
+ if src != "" {
+ return avatarHTML(src, size, class, user.DisplayName())
+ }
+ }
+
+ if repo, ok := item.(*models.Repository); ok {
+ src := repo.RelAvatarLink()
+ if src != "" {
+ return avatarHTML(src, size, class, repo.FullName())
+ }
+ }
+
+ return template.HTML("")
+}
+
+// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string)
+func AvatarByEmail(email string, name string, others ...interface{}) template.HTML {
+ size, class := parseOthers(28, "ui avatar image", others...)
+ src := models.SizedAvatarLink(email, size*2) // request double size for finer rendering
+
+ if src != "" {
+ return avatarHTML(src, size, class, name)
+ }
+
+ return template.HTML("")
+}
+
// Safe render raw as HTML
func Safe(raw string) template.HTML {
return template.HTML(raw)
diff --git a/routers/repo/blame.go b/routers/repo/blame.go
index 812c55ea4..bd1131098 100644
--- a/routers/repo/blame.go
+++ b/routers/repo/blame.go
@@ -10,7 +10,6 @@ import (
"fmt"
"html"
gotemplate "html/template"
- "net/url"
"strings"
"code.gitea.io/gitea/models"
@@ -19,7 +18,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
)
@@ -209,17 +208,15 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
commit := commitNames[part.Sha]
if index == 0 {
// User avatar image
- avatar := ""
commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string))
+
+ var avatar string
if commit.User != nil {
- authorName := commit.Author.Name
- if len(commit.User.FullName) > 0 {
- authorName = commit.User.FullName
- }
- avatar = fmt.Sprintf(`
`, setting.AppSubURL, url.PathEscape(commit.User.Name), commit.User.RelAvatarLink(), html.EscapeString(authorName))
+ avatar = string(templates.Avatar(commit.User, 18, "mr-3"))
} else {
- avatar = fmt.Sprintf(`
`, html.EscapeString(models.AvatarLink(commit.Author.Email)), html.EscapeString(commit.Author.Name))
+ avatar = string(templates.AvatarByEmail(commit.Author.Email, commit.Author.Name, 18, "mr-3"))
}
+
commitInfo.WriteString(fmt.Sprintf(`
{{- if .CanCommitToBranch.WillSign}} {{svg "octicon-lock" 24}} diff --git a/templates/repo/forks.tmpl b/templates/repo/forks.tmpl index 28547f1af..192291275 100644 --- a/templates/repo/forks.tmpl +++ b/templates/repo/forks.tmpl @@ -8,7 +8,7 @@
{{range .Forks}}
-
+ {{avatar .Owner}}
{{.Owner.Name}}
/
diff --git a/templates/repo/graph/commits.tmpl b/templates/repo/graph/commits.tmpl
index d89bcf1cc..9f7a6c1c6 100644
--- a/templates/repo/graph/commits.tmpl
+++ b/templates/repo/graph/commits.tmpl
@@ -67,9 +67,11 @@
{{if $commit.User.FullName}}
{{$userName = $commit.User.FullName}}
{{end}}
-
{{$userName}}
+ {{avatar $commit.User}}
+ {{$userName}}
{{else}}
-
{{$userName}}
+ {{avatarByEmail $commit.Commit.Author.Email $userName}}
+ {{$userName}}
{{end}}
{{$commit.Date}}
diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl
index 51f49b599..348c6b1ff 100644
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -3,8 +3,8 @@
- {{if .RelAvatarLink}}
-
+ {{if .Name}}
+ {{avatar .}}
{{else}}
{{template "repo/header_icon" .}}
{{end}}
diff --git a/templates/repo/header_icon.tmpl b/templates/repo/header_icon.tmpl
index 7883ee9bc..b9d49c209 100644
--- a/templates/repo/header_icon.tmpl
+++ b/templates/repo/header_icon.tmpl
@@ -7,7 +7,7 @@
{{else if and (not $.IsMirror) (not $.IsFork) ($.Owner)}}
{{svg "octicon-repo" 32}}
{{if $.Owner.Visibility.IsPrivate}}
-
+ {{avatar $.Owner}}
{{end}}
{{else if $.IsMirror}}
{{svg "octicon-mirror" 32}}
diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl
index 6125c01b7..2b64d2670 100644
--- a/templates/repo/issue/list.tmpl
+++ b/templates/repo/issue/list.tmpl
@@ -70,7 +70,9 @@
{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}
{{range .Assignees}}
-
{{.GetDisplayName}}
+
+ {{avatar .}}
+
{{end}}
@@ -173,7 +175,7 @@
{{range .Assignees}}
-
{{.GetDisplayName}}
+ {{avatar .}}
{{end}}
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl
index 9f0a2f99a..638134c44 100644
--- a/templates/repo/issue/milestone_issues.tmpl
+++ b/templates/repo/issue/milestone_issues.tmpl
@@ -68,7 +68,10 @@
{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}
{{range .Assignees}}
-
{{.GetDisplayName}}
+
+ {{avatar . 28 "mr-2"}}
+ {{.GetDisplayName}}
+
{{end}}
@@ -151,7 +154,8 @@
{{range .Assignees}}
-
{{.GetDisplayName}}
+ {{avatar . 28 "mr-2"}}
+ {{.GetDisplayName}}
{{end}}
diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl
index 4814ba590..aa142e3de 100644
--- a/templates/repo/issue/new_form.tmpl
+++ b/templates/repo/issue/new_form.tmpl
@@ -9,7 +9,7 @@
-
+ {{avatar .SignedUser}}
@@ -219,7 +219,7 @@
{{svg "octicon-check"}}
-
{{.GetDisplayName}}
+ {{avatar . 28 "mr-3"}}{{.GetDisplayName}}
{{end}}
@@ -231,7 +231,7 @@
{{range .Assignees}}
-
{{.GetDisplayName}}
+ {{avatar . 28 "mr-3 vm"}}{{.GetDisplayName}}
{{end}}
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl
index 81e2c80c3..355ba0ea2 100644
--- a/templates/repo/issue/view_content.tmpl
+++ b/templates/repo/issue/view_content.tmpl
@@ -16,7 +16,7 @@
{{else}}
-
+ {{avatar .Issue.Poster}}
{{end}}
@@ -93,7 +93,7 @@
{{ if and (or .IsRepoAdmin .HasIssuesOrPullsWritePermission (not .Issue.IsLocked)) (not .Repository.IsArchived) }}
-
+ {{avatar .SignedUser}}