mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-30 19:08:37 +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:
		| @@ -140,12 +140,6 @@ func (a *Action) GetDisplayNameTitle() string { | |||||||
| 	return a.GetActFullName() | 	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. | // GetRepoUserName returns the name of the action repository owner. | ||||||
| func (a *Action) GetRepoUserName() string { | func (a *Action) GetRepoUserName() string { | ||||||
| 	a.loadRepo() | 	a.loadRepo() | ||||||
|   | |||||||
| @@ -8,9 +8,13 @@ import ( | |||||||
| 	"crypto/md5" | 	"crypto/md5" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" | 	"net/url" | ||||||
|  | 	"path" | ||||||
|  | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/cache" | 	"code.gitea.io/gitea/modules/cache" | ||||||
|  | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -20,6 +24,28 @@ type EmailHash struct { | |||||||
| 	Email string `xorm:"UNIQUE NOT NULL"` | 	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 | // GetEmailForHash converts a provided md5sum to the email | ||||||
| func GetEmailForHash(md5Sum string) (string, error) { | func GetEmailForHash(md5Sum string) (string, error) { | ||||||
| 	return cache.GetString("Avatar:"+md5Sum, func() (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 | // LibravatarURL returns the URL for the given email. This function should only | ||||||
| func AvatarLink(email string) string { | // 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)) | 	lowerEmail := strings.ToLower(strings.TrimSpace(email)) | ||||||
| 	sum := fmt.Sprintf("%x", md5.Sum([]byte(lowerEmail))) | 	sum := fmt.Sprintf("%x", md5.Sum([]byte(lowerEmail))) | ||||||
| 	_, _ = cache.GetString("Avatar:"+sum, func() (string, error) { | 	_, _ = cache.GetString("Avatar:"+sum, func() (string, error) { | ||||||
| @@ -57,3 +99,34 @@ func AvatarLink(email string) string { | |||||||
| 	}) | 	}) | ||||||
| 	return setting.AppSubURL + "/avatar/" + url.PathEscape(sum) | 	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) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								models/avatar_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								models/avatar_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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), | ||||||
|  | 	) | ||||||
|  | } | ||||||
| @@ -13,7 +13,6 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/modules/avatar" | 	"code.gitea.io/gitea/modules/avatar" | ||||||
| 	"code.gitea.io/gitea/modules/base" |  | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/storage" | 	"code.gitea.io/gitea/modules/storage" | ||||||
| @@ -41,7 +40,7 @@ func (u *User) generateRandomAvatar(e Engine) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if u.Avatar == "" { | 	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 { | 	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 { | func (u *User) RealSizedAvatarLink(size int) string { | ||||||
| 	if u.ID == -1 { | 	if u.ID == -1 { | ||||||
| 		return base.DefaultAvatarLink() | 		return DefaultAvatarLink() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	switch { | 	switch { | ||||||
| 	case u.UseCustomAvatar: | 	case u.UseCustomAvatar: | ||||||
| 		if u.Avatar == "" { | 		if u.Avatar == "" { | ||||||
| 			return base.DefaultAvatarLink() | 			return DefaultAvatarLink() | ||||||
| 		} | 		} | ||||||
| 		return setting.AppSubURL + "/avatars/" + u.Avatar | 		return setting.AppSubURL + "/avatars/" + u.Avatar | ||||||
| 	case setting.DisableGravatar, setting.OfflineMode: | 	case setting.DisableGravatar, setting.OfflineMode: | ||||||
| @@ -94,14 +93,14 @@ func (u *User) RealSizedAvatarLink(size int) string { | |||||||
|  |  | ||||||
| 		return setting.AppSubURL + "/avatars/" + u.Avatar | 		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 | // 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 | // may either be a sub-URL to this site, or a full URL to an external avatar | ||||||
| // service. | // service. | ||||||
| func (u *User) RelAvatarLink() string { | func (u *User) RelAvatarLink() string { | ||||||
| 	return u.SizedRelAvatarLink(base.DefaultAvatarSize) | 	return u.SizedRelAvatarLink(DefaultAvatarSize) | ||||||
| } | } | ||||||
|  |  | ||||||
| // AvatarLink returns user avatar absolute link. | // AvatarLink returns user avatar absolute link. | ||||||
|   | |||||||
| @@ -168,7 +168,7 @@ func (s *SSPI) newUser(ctx *macaron.Context, username string, cfg *models.SSPICo | |||||||
| 		IsActive:                     cfg.AutoActivateUsers, | 		IsActive:                     cfg.AutoActivateUsers, | ||||||
| 		Language:                     cfg.DefaultLanguage, | 		Language:                     cfg.DefaultLanguage, | ||||||
| 		UseCustomAvatar:              true, | 		UseCustomAvatar:              true, | ||||||
| 		Avatar:                       base.DefaultAvatarLink(), | 		Avatar:                       models.DefaultAvatarLink(), | ||||||
| 		EmailNotificationsPreference: models.EmailNotificationsDisabled, | 		EmailNotificationsPreference: models.EmailNotificationsDisabled, | ||||||
| 	} | 	} | ||||||
| 	if err := models.CreateUser(user); err != nil { | 	if err := models.CreateUser(user); err != nil { | ||||||
|   | |||||||
| @@ -12,9 +12,7 @@ import ( | |||||||
| 	"encoding/hex" | 	"encoding/hex" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/url" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" |  | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| @@ -134,93 +132,6 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string | |||||||
| 	return code | 	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. | // FileSize calculates the file size and generate user-friendly string. | ||||||
| func FileSize(s int64) string { | func FileSize(s int64) string { | ||||||
| 	return humanize.IBytes(uint64(s)) | 	return humanize.IBytes(uint64(s)) | ||||||
|   | |||||||
| @@ -5,11 +5,8 @@ | |||||||
| package base | package base | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"net/url" |  | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/modules/setting" |  | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -56,44 +53,6 @@ func TestBasicAuthEncode(t *testing.T) { | |||||||
| // TODO: Test VerifyTimeLimitCode() | // TODO: Test VerifyTimeLimitCode() | ||||||
| // TODO: Test CreateTimeLimitCode() | // 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) { | func TestFileSize(t *testing.T) { | ||||||
| 	var size int64 = 512 | 	var size int64 = 512 | ||||||
| 	assert.Equal(t, "512 B", FileSize(size)) | 	assert.Equal(t, "512 B", FileSize(size)) | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ func (pc *PushCommits) AvatarLink(email string) string { | |||||||
| 		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.AvatarLink(email) | 			pc.avatars[email] = models.HashedAvatarLink(email) | ||||||
| 			if !models.IsErrUserNotExist(err) { | 			if !models.IsErrUserNotExist(err) { | ||||||
| 				log.Error("GetUserByEmail: %v", err) | 				log.Error("GetUserByEmail: %v", err) | ||||||
| 				return "" | 				return "" | ||||||
|   | |||||||
| @@ -88,7 +88,6 @@ func NewFuncMap() []template.FuncMap { | |||||||
| 		"AllowedReactions": func() []string { | 		"AllowedReactions": func() []string { | ||||||
| 			return setting.UI.Reactions | 			return setting.UI.Reactions | ||||||
| 		}, | 		}, | ||||||
| 		"AvatarLink":    models.AvatarLink, |  | ||||||
| 		"Safe":          Safe, | 		"Safe":          Safe, | ||||||
| 		"SafeJS":        SafeJS, | 		"SafeJS":        SafeJS, | ||||||
| 		"Str2html":      Str2html, | 		"Str2html":      Str2html, | ||||||
| @@ -339,7 +338,9 @@ func NewFuncMap() []template.FuncMap { | |||||||
| 			} | 			} | ||||||
| 			return false | 			return false | ||||||
| 		}, | 		}, | ||||||
| 		"svg": SVG, | 		"svg":           SVG, | ||||||
|  | 		"avatar":        Avatar, | ||||||
|  | 		"avatarByEmail": AvatarByEmail, | ||||||
| 		"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML { | 		"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML { | ||||||
| 			// if needed | 			// if needed | ||||||
| 			if len(normSort) == 0 || len(urlSort) == 0 { | 			if len(normSort) == 0 || len(urlSort) == 0 { | ||||||
| @@ -499,18 +500,38 @@ func NewTextFuncMap() []texttmpl.FuncMap { | |||||||
| var widthRe = regexp.MustCompile(`width="[0-9]+?"`) | var widthRe = regexp.MustCompile(`width="[0-9]+?"`) | ||||||
| var heightRe = regexp.MustCompile(`height="[0-9]+?"`) | var heightRe = regexp.MustCompile(`height="[0-9]+?"`) | ||||||
|  |  | ||||||
| // SVG render icons - arguments icon name (string), size (int), class (string) | func parseOthers(defaultSize int, defaultClass string, others ...interface{}) (int, string) { | ||||||
| func SVG(icon string, others ...interface{}) template.HTML { | 	size := defaultSize | ||||||
| 	size := 16 |  | ||||||
| 	if len(others) > 0 && others[0].(int) != 0 { | 	if len(others) > 0 && others[0].(int) != 0 { | ||||||
| 		size = others[0].(int) | 		size = others[0].(int) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	class := "" | 	class := defaultClass | ||||||
| 	if len(others) > 1 && others[1].(string) != "" { | 	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(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 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 svgStr, ok := svg.SVGs[icon]; ok { | ||||||
| 		if size != 16 { | 		if size != 16 { | ||||||
| 			svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size)) | 			svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size)) | ||||||
| @@ -524,6 +545,38 @@ func SVG(icon string, others ...interface{}) template.HTML { | |||||||
| 	return 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 | // Safe render raw as HTML | ||||||
| func Safe(raw string) template.HTML { | func Safe(raw string) template.HTML { | ||||||
| 	return template.HTML(raw) | 	return template.HTML(raw) | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"html" | 	"html" | ||||||
| 	gotemplate "html/template" | 	gotemplate "html/template" | ||||||
| 	"net/url" |  | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| @@ -19,7 +18,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/highlight" | 	"code.gitea.io/gitea/modules/highlight" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -209,17 +208,15 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m | |||||||
| 			commit := commitNames[part.Sha] | 			commit := commitNames[part.Sha] | ||||||
| 			if index == 0 { | 			if index == 0 { | ||||||
| 				// User avatar image | 				// User avatar image | ||||||
| 				avatar := "" |  | ||||||
| 				commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string)) | 				commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string)) | ||||||
|  |  | ||||||
|  | 				var avatar string | ||||||
| 				if commit.User != nil { | 				if commit.User != nil { | ||||||
| 					authorName := commit.Author.Name | 					avatar = string(templates.Avatar(commit.User, 18, "mr-3")) | ||||||
| 					if len(commit.User.FullName) > 0 { |  | ||||||
| 						authorName = commit.User.FullName |  | ||||||
| 					} |  | ||||||
| 					avatar = fmt.Sprintf(`<a href="%s/%s"><img class="ui avatar image" src="%s" title="%s" alt=""/></a>`, setting.AppSubURL, url.PathEscape(commit.User.Name), commit.User.RelAvatarLink(), html.EscapeString(authorName)) |  | ||||||
| 				} else { | 				} else { | ||||||
| 					avatar = fmt.Sprintf(`<img class="ui avatar image" src="%s" title="%s"/>`, 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(`<div class="blame-info%s"><div class="blame-data"><div class="blame-avatar">%s</div><div class="blame-message"><a href="%s/commit/%s" title="%[5]s">%[5]s</a></div><div class="blame-time">%s</div></div></div>`, attr, avatar, repoLink, part.Sha, html.EscapeString(commit.CommitMessage), commitSince)) | 				commitInfo.WriteString(fmt.Sprintf(`<div class="blame-info%s"><div class="blame-data"><div class="blame-avatar">%s</div><div class="blame-message"><a href="%s/commit/%s" title="%[5]s">%[5]s</a></div><div class="blame-time">%s</div></div></div>`, attr, avatar, repoLink, part.Sha, html.EscapeString(commit.CommitMessage), commitSince)) | ||||||
| 			} else { | 			} else { | ||||||
| 				commitInfo.WriteString(fmt.Sprintf(`<div class="blame-info%s">​</div>`, attr)) | 				commitInfo.WriteString(fmt.Sprintf(`<div class="blame-info%s">​</div>`, attr)) | ||||||
|   | |||||||
| @@ -6,11 +6,11 @@ package user | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/base" |  | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| ) | ) | ||||||
| @@ -46,23 +46,38 @@ func Avatar(ctx *context.Context) { | |||||||
|  |  | ||||||
| // AvatarByEmailHash redirects the browser to the appropriate Avatar link | // AvatarByEmailHash redirects the browser to the appropriate Avatar link | ||||||
| func AvatarByEmailHash(ctx *context.Context) { | func AvatarByEmailHash(ctx *context.Context) { | ||||||
|  | 	var err error | ||||||
|  |  | ||||||
| 	hash := ctx.Params(":hash") | 	hash := ctx.Params(":hash") | ||||||
| 	if len(hash) == 0 { | 	if len(hash) == 0 { | ||||||
| 		ctx.ServerError("invalid avatar hash", errors.New("hash cannot be empty")) | 		ctx.ServerError("invalid avatar hash", errors.New("hash cannot be empty")) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	email, err := models.GetEmailForHash(hash) |  | ||||||
|  | 	var email string | ||||||
|  | 	email, err = models.GetEmailForHash(hash) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("invalid avatar hash", err) | 		ctx.ServerError("invalid avatar hash", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	if len(email) == 0 { | 	if len(email) == 0 { | ||||||
| 		ctx.Redirect(base.DefaultAvatarLink()) | 		ctx.Redirect(models.DefaultAvatarLink()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	size := ctx.QueryInt("size") | 	size := ctx.QueryInt("size") | ||||||
| 	if size == 0 { | 	if size == 0 { | ||||||
| 		size = base.DefaultAvatarSize | 		size = models.DefaultAvatarSize | ||||||
| 	} | 	} | ||||||
| 	ctx.Redirect(base.SizedAvatarLinkWithDomain(email, size)) |  | ||||||
|  | 	var avatarURL *url.URL | ||||||
|  | 	avatarURL, err = models.LibravatarURL(email) | ||||||
|  | 	if err != nil { | ||||||
|  | 		avatarURL, err = url.Parse(models.DefaultAvatarLink()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.ServerError("invalid default avatar url", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Redirect(models.MakeFinalAvatarURL(avatarURL, size)) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ | |||||||
| 		<div class="right stackable menu"> | 		<div class="right stackable menu"> | ||||||
| 			<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | 			<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | ||||||
| 				<span class="text"> | 				<span class="text"> | ||||||
| 					<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | 					{{avatar .SignedUser 24 "tiny"}} | ||||||
| 					<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | 					<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | ||||||
| 					<span class="mobile-only">{{.SignedUser.Name}}</span> | 					<span class="mobile-only">{{.SignedUser.Name}}</span> | ||||||
| 					<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down"}}</span> | 					<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down"}}</span> | ||||||
| @@ -102,7 +102,7 @@ | |||||||
|  |  | ||||||
| 			<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | 			<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | ||||||
| 				<span class="text"> | 				<span class="text"> | ||||||
| 					<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | 					{{avatar .SignedUser 24 "tiny"}} | ||||||
| 					<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | 					<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | ||||||
| 					<span class="mobile-only">{{.SignedUser.Name}}</span> | 					<span class="mobile-only">{{.SignedUser.Name}}</span> | ||||||
| 					<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down"}}</span> | 					<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down"}}</span> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| 		<div class="ui user list"> | 		<div class="ui user list"> | ||||||
| 			{{range .Users}} | 			{{range .Users}} | ||||||
| 				<div class="item"> | 				<div class="item"> | ||||||
| 				  <img class="ui avatar image" src="{{.RelAvatarLink}}"> | 					{{avatar .}} | ||||||
| 				  <div class="content"> | 				  <div class="content"> | ||||||
| 					<span class="header"> | 					<span class="header"> | ||||||
| 						<a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}} | 						<a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}} | ||||||
|   | |||||||
| @@ -2,9 +2,7 @@ | |||||||
| 	{{range .Repos}} | 	{{range .Repos}} | ||||||
| 		<div class="item"> | 		<div class="item"> | ||||||
| 			<div class="ui header"> | 			<div class="ui header"> | ||||||
| 				{{if .RelAvatarLink}} | 				{{avatar .}} | ||||||
| 					<img class="ui avatar image" src="{{.RelAvatarLink}}"> |  | ||||||
| 				{{end}} |  | ||||||
| 				<a class="name" href="{{.Link}}"> | 				<a class="name" href="{{.Link}}"> | ||||||
| 					{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{.Name}} | 					{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{.Name}} | ||||||
| 				</a> | 				</a> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| 		<div class="ui user list"> | 		<div class="ui user list"> | ||||||
| 			{{range .Users}} | 			{{range .Users}} | ||||||
| 				<div class="item"> | 				<div class="item"> | ||||||
| 				  <img class="ui avatar image" src="{{.RelAvatarLink}}"> | 					{{avatar .}} | ||||||
| 				  <div class="content"> | 				  <div class="content"> | ||||||
| 					<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span> | 					<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span> | ||||||
| 					<div class="description"> | 					<div class="description"> | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| 		<div class="ui vertically grid head"> | 		<div class="ui vertically grid head"> | ||||||
| 			<div class="column"> | 			<div class="column"> | ||||||
| 				<div class="ui header"> | 				<div class="ui header"> | ||||||
| 					<img class="ui image" src="{{.SizedRelAvatarLink 100}}"> | 					{{avatar . 100}} | ||||||
| 					<span class="text thin grey"><a href="{{.HomeLink}}">{{.DisplayName}}</a></span> | 					<span class="text thin grey"><a href="{{.HomeLink}}">{{.DisplayName}}</a></span> | ||||||
| 					<span class="org-visibility"> | 					<span class="org-visibility"> | ||||||
| 						{{if .Visibility.IsLimited}}<div class="ui medium orange horizontal label">{{$.i18n.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | 						{{if .Visibility.IsLimited}}<div class="ui medium orange horizontal label">{{$.i18n.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | ||||||
|   | |||||||
| @@ -1,9 +1,7 @@ | |||||||
| {{template "base/head" .}} | {{template "base/head" .}} | ||||||
| <div class="page-content organization profile"> | <div class="page-content organization profile"> | ||||||
| 	{{/* overflow: auto is the clearfix - this avoids the image going beyond | 	<div class="ui container df"> | ||||||
| 	the container where it is supposed to stay inside. */}} | 		{{avatar .Org 140 "org-avatar"}} | ||||||
| 	<div class="ui container" style="overflow: auto"> |  | ||||||
| 		<img class="ui left" id="org-avatar" src="{{.Org.SizedRelAvatarLink 140}}"/> |  | ||||||
| 		<div id="org-info"> | 		<div id="org-info"> | ||||||
| 			<div class="ui header"> | 			<div class="ui header"> | ||||||
| 				{{.Org.DisplayName}} | 				{{.Org.DisplayName}} | ||||||
| @@ -53,7 +51,9 @@ | |||||||
| 					{{$isMember := .IsOrganizationMember}} | 					{{$isMember := .IsOrganizationMember}} | ||||||
| 					{{range .Members}} | 					{{range .Members}} | ||||||
| 						{{if or $isMember (.IsPublicMember $.Org.ID)}} | 						{{if or $isMember (.IsPublicMember $.Org.ID)}} | ||||||
| 							<a href="{{.HomeLink}}" title="{{.Name}}{{if .FullName}} ({{.FullName}}){{end}}"><img class="ui avatar" src="{{.RelAvatarLink}}"></a> | 							<a href="{{.HomeLink}}" title="{{.Name}}{{if .FullName}} ({{.FullName}}){{end}}"> | ||||||
|  | 								{{avatar .}} | ||||||
|  | 							</a> | ||||||
| 						{{end}} | 						{{end}} | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 				</div> | 				</div> | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 			{{ range .Members}} | 			{{ range .Members}} | ||||||
| 				<div class="item ui grid"> | 				<div class="item ui grid"> | ||||||
| 					<div class="ui one wide column"> | 					<div class="ui one wide column"> | ||||||
| 						<img class="ui avatar" src="{{.SizedRelAvatarLink 48}}"> | 						{{avatar . 48}} | ||||||
| 					</div> | 					</div> | ||||||
| 					<div class="ui three wide column"> | 					<div class="ui three wide column"> | ||||||
| 						<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div> | 						<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div> | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
| 								</form> | 								</form> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 							<a href="{{.HomeLink}}"> | 							<a href="{{.HomeLink}}"> | ||||||
| 								<img class="ui avatar image" src="{{.RelAvatarLink}}"> | 								{{avatar .}} | ||||||
| 								{{.DisplayName}} | 								{{.DisplayName}} | ||||||
| 							</a> | 							</a> | ||||||
| 						</div> | 						</div> | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| 					<div class="ui attached segment members"> | 					<div class="ui attached segment members"> | ||||||
| 						{{range .Members}} | 						{{range .Members}} | ||||||
| 							<a href="{{.HomeLink}}" title="{{.Name}}"> | 							<a href="{{.HomeLink}}" title="{{.Name}}"> | ||||||
| 								<img class="ui avatar image" src="{{.RelAvatarLink}}"> | 								{{avatar .}} | ||||||
| 							</a> | 							</a> | ||||||
| 						{{end}} | 						{{end}} | ||||||
| 					</div> | 					</div> | ||||||
|   | |||||||
| @@ -38,14 +38,14 @@ | |||||||
| 			<div class="ui stackable grid"> | 			<div class="ui stackable grid"> | ||||||
| 				<div class="nine wide column"> | 				<div class="nine wide column"> | ||||||
| 					{{if .Author}} | 					{{if .Author}} | ||||||
| 						<img class="ui avatar image" src="{{.Author.RelAvatarLink}}" /> | 						{{avatar .Author}} | ||||||
| 					{{if .Author.FullName}} | 						{{if .Author.FullName}} | ||||||
| 					<a href="{{.Author.HomeLink}}"><strong>{{.Author.FullName}}</strong></a> | 							<a href="{{.Author.HomeLink}}"><strong>{{.Author.FullName}}</strong></a> | ||||||
|  | 						{{else}} | ||||||
|  | 							<a href="{{.Author.HomeLink}}"><strong>{{.Commit.Author.Name}}</strong></a> | ||||||
|  | 						{{end}} | ||||||
| 					{{else}} | 					{{else}} | ||||||
| 					<a href="{{.Author.HomeLink}}"><strong>{{.Commit.Author.Name}}</strong></a> | 						{{avatarByEmail .Commit.Author.Email .Commit.Author.Email 12}} | ||||||
| 					{{end}} |  | ||||||
| 					{{else}} |  | ||||||
| 						<img class="ui avatar image" src="{{AvatarLink .Commit.Author.Email}}" /> |  | ||||||
| 						<strong>{{.Commit.Author.Name}}</strong> | 						<strong>{{.Commit.Author.Name}}</strong> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 					<span class="text grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span> | 					<span class="text grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span> | ||||||
| @@ -53,10 +53,10 @@ | |||||||
| 						<div class="committed-by"> | 						<div class="committed-by"> | ||||||
| 							<span class="text grey">{{svg "octicon-git-commit"}}{{.i18n.Tr "repo.diff.committed_by"}}</span> | 							<span class="text grey">{{svg "octicon-git-commit"}}{{.i18n.Tr "repo.diff.committed_by"}}</span> | ||||||
| 							{{if ne .Verification.CommittingUser.ID 0}} | 							{{if ne .Verification.CommittingUser.ID 0}} | ||||||
| 								<img class="ui avatar image" src="{{.Verification.CommittingUser.RelAvatarLink}}" /> | 								{{avatar .Verification.CommittingUser}} | ||||||
| 								<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong></a> | 								<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong></a> | ||||||
| 							{{else}} | 							{{else}} | ||||||
| 								<img class="ui avatar image" src="{{AvatarLink .Commit.Committer.Email}}" /> | 								{{avatarByEmail .Commit.Committer.Email .Commit.Committer.Name}} | ||||||
| 								<strong>{{.Commit.Committer.Name}}</strong> | 								<strong>{{.Commit.Committer.Name}}</strong> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</div> | 						</div> | ||||||
| @@ -98,13 +98,13 @@ | |||||||
| 						{{else}} | 						{{else}} | ||||||
| 							<span class="ui text">{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}:</span> | 							<span class="ui text">{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}:</span> | ||||||
| 						{{end}} | 						{{end}} | ||||||
| 						<img class="ui avatar image" src="{{.Verification.SigningUser.RelAvatarLink}}" /> | 						{{avatar .Verification.SigningUser}} | ||||||
| 						<a href="{{.Verification.SigningUser.HomeLink}}"><strong>{{.Verification.SigningUser.Name}}</strong></a> | 						<a href="{{.Verification.SigningUser.HomeLink}}"><strong>{{.Verification.SigningUser.Name}}</strong></a> | ||||||
| 						<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> {{.Verification.SigningKey.KeyID}}</span> | 						<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> {{.Verification.SigningKey.KeyID}}</span> | ||||||
| 					{{else}} | 					{{else}} | ||||||
| 						<span title="{{.i18n.Tr "gpg.default_key"}}">{{svg "gitea-lock-cog"}}</span> | 						<span title="{{.i18n.Tr "gpg.default_key"}}">{{svg "gitea-lock-cog"}}</span> | ||||||
| 						<span class="ui text">{{.i18n.Tr "repo.commits.signed_by"}}:</span> | 						<span class="ui text">{{.i18n.Tr "repo.commits.signed_by"}}:</span> | ||||||
| 						<img class="ui avatar image" src="{{AvatarLink .Verification.SigningEmail}}" /> | 						{{avatarByEmail .Verification.SigningEmail ""}} | ||||||
| 						<strong>{{.Verification.SigningUser.Name}}</strong> | 						<strong>{{.Verification.SigningUser.Name}}</strong> | ||||||
| 						<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="cogs icon" title="{{.i18n.Tr "gpg.default_key"}}"></i>{{.Verification.SigningKey.KeyID}}</span> | 						<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="cogs icon" title="{{.i18n.Tr "gpg.default_key"}}"></i>{{.Verification.SigningKey.KeyID}}</span> | ||||||
| 					{{end}} | 					{{end}} | ||||||
|   | |||||||
| @@ -18,9 +18,10 @@ | |||||||
| 								{{if .User.FullName}} | 								{{if .User.FullName}} | ||||||
| 									{{$userName = .User.FullName}} | 									{{$userName = .User.FullName}} | ||||||
| 								{{end}} | 								{{end}} | ||||||
| 								<img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/>  <a href="{{AppSubUrl}}/{{.User.Name}}">{{$userName}}</a> | 								{{avatar .User 28 "mr-2"}}<a href="{{AppSubUrl}}/{{.User.Name}}">{{$userName}}</a> | ||||||
| 							{{else}} | 							{{else}} | ||||||
| 								<img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/>  {{$userName}} | 								{{avatarByEmail .Author.Email .Author.Name 28 "mr-2"}} | ||||||
|  | 								{{$userName}} | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</td> | 						</td> | ||||||
| 						<td class="sha"> | 						<td class="sha"> | ||||||
|   | |||||||
| @@ -7,9 +7,11 @@ | |||||||
| 	<div class="singular-commit" id="{{$tag}}"> | 	<div class="singular-commit" id="{{$tag}}"> | ||||||
| 		<span class="badge badge-commit">{{svg "octicon-git-commit"}}</span> | 		<span class="badge badge-commit">{{svg "octicon-git-commit"}}</span> | ||||||
| 		{{if .User}} | 		{{if .User}} | ||||||
| 			<a class="ui avatar image" href="{{AppSubUrl}}/{{.User.Name}}"><img src="{{.User.RelAvatarLink}}" alt=""/></a> | 			<a href="{{AppSubUrl}}/{{.User.Name}}"> | ||||||
|  | 				{{avatar .User}} | ||||||
|  | 			</a> | ||||||
| 		{{else}} | 		{{else}} | ||||||
| 			<img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/> | 			{{avatarByEmail .Author.Email .Author.Name}} | ||||||
| 		{{end}} | 		{{end}} | ||||||
|  |  | ||||||
| 		<span class="ui float right shabox"> | 		<span class="ui float right shabox"> | ||||||
|   | |||||||
| @@ -14,18 +14,18 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser 28 "mini"}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu"> | 							<div class="menu"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 									{{avatar .SignedUser 28 "mini"}} | ||||||
| 									{{.SignedUser.ShortName 20}} | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 										{{.ShortName 20}} | 										{{.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| 		<span class="avatar"><img src="/img/avatar_default.png"></span> | 		<span class="avatar"><img src="/img/avatar_default.png"></span> | ||||||
| 	{{else}} | 	{{else}} | ||||||
| 		<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}> | 		<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}> | ||||||
| 			<img src="{{.Poster.RelAvatarLink}}"> | 			{{avatar .Poster}} | ||||||
| 		</a> | 		</a> | ||||||
| 	{{end}} | 	{{end}} | ||||||
| 	<div class="content comment-container"> | 	<div class="content comment-container"> | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <div class="commit-form-wrapper"> | <div class="commit-form-wrapper"> | ||||||
| 	<img width="48" height="48" class="ui image commit-avatar" src="{{.SignedUser.RelAvatarLink}}"> | 	{{avatar .SignedUser 48 "commit-avatar"}} | ||||||
| 	<div class="commit-form"> | 	<div class="commit-form"> | ||||||
| 		<h3>{{- if .CanCommitToBranch.WillSign}} | 		<h3>{{- if .CanCommitToBranch.WillSign}} | ||||||
| 			<span title="{{.i18n.Tr "repo.signing.will_sign" .CanCommitToBranch.SigningKey}}">{{svg "octicon-lock" 24}}</span> | 			<span title="{{.i18n.Tr "repo.signing.will_sign" .CanCommitToBranch.SigningKey}}">{{svg "octicon-lock" 24}}</span> | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 		<div class="ui list"> | 		<div class="ui list"> | ||||||
| 			{{range .Forks}} | 			{{range .Forks}} | ||||||
| 				<div class="item"> | 				<div class="item"> | ||||||
| 					<img class="ui avatar image" src="{{.Owner.RelAvatarLink}}"> | 					{{avatar .Owner}} | ||||||
| 					<div class="link"> | 					<div class="link"> | ||||||
| 						<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a> | 						<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a> | ||||||
| 						/ | 						/ | ||||||
|   | |||||||
| @@ -67,9 +67,11 @@ | |||||||
| 							{{if $commit.User.FullName}} | 							{{if $commit.User.FullName}} | ||||||
| 								{{$userName = $commit.User.FullName}} | 								{{$userName = $commit.User.FullName}} | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 							<img class="ui avatar image" src="{{$commit.User.RelAvatarLink}}" alt=""/><a href="{{AppSubUrl}}/{{$commit.User.Name}}">{{$userName}}</a> | 							{{avatar $commit.User}} | ||||||
|  | 							<a href="{{AppSubUrl}}/{{$commit.User}}">{{$userName}}</a> | ||||||
| 						{{else}} | 						{{else}} | ||||||
| 							<img class="ui avatar image" src="{{AvatarLink $commit.Commit.Author.Email}}" alt=""/>{{$userName}} | 							{{avatarByEmail $commit.Commit.Author.Email $userName}} | ||||||
|  | 							{{$userName}} | ||||||
| 						{{end}} | 						{{end}} | ||||||
| 					</span> | 					</span> | ||||||
| 					<span class="time df ac">{{$commit.Date}}</span> | 					<span class="time df ac">{{$commit.Date}}</span> | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ | |||||||
| 	<div class="ui container"> | 	<div class="ui container"> | ||||||
| 		<div class="repo-header"> | 		<div class="repo-header"> | ||||||
| 			<div class="ui huge breadcrumb repo-title"> | 			<div class="ui huge breadcrumb repo-title"> | ||||||
| 				{{if .RelAvatarLink}} | 				{{if .Name}} | ||||||
| 					<img class="ui avatar image" src="{{.RelAvatarLink}}"> | 					{{avatar .}} | ||||||
| 				{{else}} | 				{{else}} | ||||||
| 					{{template "repo/header_icon" .}} | 					{{template "repo/header_icon" .}} | ||||||
| 				{{end}} | 				{{end}} | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| 		{{else if and (not $.IsMirror) (not $.IsFork) ($.Owner)}} | 		{{else if and (not $.IsMirror) (not $.IsFork) ($.Owner)}} | ||||||
| 			{{svg "octicon-repo" 32}} | 			{{svg "octicon-repo" 32}} | ||||||
| 			{{if $.Owner.Visibility.IsPrivate}} | 			{{if $.Owner.Visibility.IsPrivate}} | ||||||
| 				<img class="ui avatar image" src="{{$.Owner.RelAvatarLink}}"> | 				{{avatar $.Owner}} | ||||||
| 			{{end}} | 			{{end}} | ||||||
| 		{{else if $.IsMirror}} | 		{{else if $.IsMirror}} | ||||||
| 			{{svg "octicon-mirror" 32}} | 			{{svg "octicon-mirror" 32}} | ||||||
|   | |||||||
| @@ -70,7 +70,9 @@ | |||||||
| 						<div class="menu"> | 						<div class="menu"> | ||||||
| 							<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}">{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}</a> | 							<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}">{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}</a> | ||||||
| 							{{range .Assignees}} | 							{{range .Assignees}} | ||||||
| 								<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{.ID}}"><img src="{{.RelAvatarLink}}"> {{.GetDisplayName}}</a> | 								<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{.ID}}"> | ||||||
|  | 									{{avatar .}} | ||||||
|  | 								</a> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| @@ -173,7 +175,7 @@ | |||||||
| 							</div> | 							</div> | ||||||
| 							{{range .Assignees}} | 							{{range .Assignees}} | ||||||
| 								<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/assignee"> | 								<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/assignee"> | ||||||
| 									<img src="{{.RelAvatarLink}}"> {{.GetDisplayName}} | 									{{avatar .}} | ||||||
| 								</div> | 								</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</div> | 						</div> | ||||||
|   | |||||||
| @@ -68,7 +68,10 @@ | |||||||
| 						<div class="menu"> | 						<div class="menu"> | ||||||
| 							<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}">{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}</a> | 							<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}">{{.i18n.Tr "repo.issues.filter_assginee_no_select"}}</a> | ||||||
| 							{{range .Assignees}} | 							{{range .Assignees}} | ||||||
| 								<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&assignee={{.ID}}"><img src="{{.RelAvatarLink}}"> {{.GetDisplayName}}</a> | 								<a class="{{if eq $.AssigneeID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&assignee={{.ID}}"> | ||||||
|  | 									{{avatar . 28 "mr-2"}} | ||||||
|  | 									{{.GetDisplayName}} | ||||||
|  | 								</a> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| @@ -151,7 +154,8 @@ | |||||||
| 							</div> | 							</div> | ||||||
| 							{{range .Assignees}} | 							{{range .Assignees}} | ||||||
| 								<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/assignee"> | 								<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/assignee"> | ||||||
| 									<img src="{{.RelAvatarLink}}"> {{.GetDisplayName}} | 									{{avatar . 28 "mr-2"}} | ||||||
|  | 									{{.GetDisplayName}} | ||||||
| 								</div> | 								</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</div> | 						</div> | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| 		<div class="ui comments"> | 		<div class="ui comments"> | ||||||
| 			<div class="comment"> | 			<div class="comment"> | ||||||
| 				<a class="avatar" href="{{.SignedUser.HomeLink}}"> | 				<a class="avatar" href="{{.SignedUser.HomeLink}}"> | ||||||
| 					<img src="{{.SignedUser.RelAvatarLink}}"> | 					{{avatar .SignedUser}} | ||||||
| 				</a> | 				</a> | ||||||
| 				<div class="ui segment content"> | 				<div class="ui segment content"> | ||||||
| 					<div class="field"> | 					<div class="field"> | ||||||
| @@ -219,7 +219,7 @@ | |||||||
| 							<a class="item muted" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}"> | 							<a class="item muted" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}"> | ||||||
| 								<span class="octicon-check invisible">{{svg "octicon-check"}}</span> | 								<span class="octicon-check invisible">{{svg "octicon-check"}}</span> | ||||||
| 								<span class="text"> | 								<span class="text"> | ||||||
| 									<img class="ui avatar image" src="{{.RelAvatarLink}}"> {{.GetDisplayName}} | 									{{avatar . 28 "mr-3"}}{{.GetDisplayName}} | ||||||
| 								</span> | 								</span> | ||||||
| 							</a> | 							</a> | ||||||
| 						{{end}} | 						{{end}} | ||||||
| @@ -231,7 +231,7 @@ | |||||||
| 					</span> | 					</span> | ||||||
| 					{{range .Assignees}} | 					{{range .Assignees}} | ||||||
| 						<a class="hide item p-2 muted" id="assignee_{{.ID}}" href="{{$.RepoLink}}/issues?assignee={{.ID}}"> | 						<a class="hide item p-2 muted" id="assignee_{{.ID}}" href="{{$.RepoLink}}/issues?assignee={{.ID}}"> | ||||||
| 							<img class="ui avatar image" src="{{.RelAvatarLink}}" style="vertical-align: middle;"> {{.GetDisplayName}} | 							{{avatar . 28 "mr-3 vm"}}{{.GetDisplayName}} | ||||||
| 						</a> | 						</a> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 				</div> | 				</div> | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ | |||||||
| 				<span class="timeline-avatar"><img src="/img/avatar_default.png"></span> | 				<span class="timeline-avatar"><img src="/img/avatar_default.png"></span> | ||||||
| 			{{else}} | 			{{else}} | ||||||
| 				<a class="timeline-avatar" {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}> | 				<a class="timeline-avatar" {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}> | ||||||
| 					<img src="{{.Issue.Poster.RelAvatarLink}}"> | 					{{avatar .Issue.Poster}} | ||||||
| 				</a> | 				</a> | ||||||
| 			{{end}} | 			{{end}} | ||||||
| 				<div class="content comment-container"> | 				<div class="content comment-container"> | ||||||
| @@ -93,7 +93,7 @@ | |||||||
| 				{{ if and (or .IsRepoAdmin .HasIssuesOrPullsWritePermission (not .Issue.IsLocked)) (not .Repository.IsArchived) }} | 				{{ if and (or .IsRepoAdmin .HasIssuesOrPullsWritePermission (not .Issue.IsLocked)) (not .Repository.IsArchived) }} | ||||||
| 				<div class="timeline-item comment form"> | 				<div class="timeline-item comment form"> | ||||||
| 					<a class="timeline-avatar" href="{{.SignedUser.HomeLink}}"> | 					<a class="timeline-avatar" href="{{.SignedUser.HomeLink}}"> | ||||||
| 						<img src="{{.SignedUser.RelAvatarLink}}"> | 						{{avatar .SignedUser}} | ||||||
| 					</a> | 					</a> | ||||||
| 					<div class="content"> | 					<div class="content"> | ||||||
| 						<form class="ui segment form" id="comment-form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/comments" method="post"> | 						<form class="ui segment form" id="comment-form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/comments" method="post"> | ||||||
| @@ -144,7 +144,7 @@ | |||||||
| 					{{if .Repository.IsArchived}} | 					{{if .Repository.IsArchived}} | ||||||
| 					<div class="timeline-item comment form"> | 					<div class="timeline-item comment form"> | ||||||
| 						<a class="timeline-avatar" href="{{.SignedUser.HomeLink}}"> | 						<a class="timeline-avatar" href="{{.SignedUser.HomeLink}}"> | ||||||
| 							<img src="{{.SignedUser.RelAvatarLink}}"> | 							{{avatar .SignedUser}} | ||||||
| 						</a> | 						</a> | ||||||
| 						<div class="content"> | 						<div class="content"> | ||||||
| 							<form class="ui segment form" id="comment-form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/comments" method="post"> | 							<form class="ui segment form" id="comment-form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/comments" method="post"> | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
| 			<span class="timeline-avatar"><img src="/img/avatar_default.png"></span> | 			<span class="timeline-avatar"><img src="/img/avatar_default.png"></span> | ||||||
| 		{{else}} | 		{{else}} | ||||||
| 			<a class="timeline-avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}> | 			<a class="timeline-avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 		{{end}} | 		{{end}} | ||||||
| 			<div class="content comment-container"> | 			<div class="content comment-container"> | ||||||
| @@ -92,8 +92,8 @@ | |||||||
| 	{{else if eq .Type 1}} | 	{{else if eq .Type 1}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge bg-green text-white">{{svg "octicon-dot-fill"}}</span> | 			<span class="badge bg-green text-white">{{svg "octicon-dot-fill"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -107,8 +107,8 @@ | |||||||
| 	{{else if eq .Type 2}} | 	{{else if eq .Type 2}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge bg-red text-white">{{svg "octicon-circle-slash"}}</span> | 			<span class="badge bg-red text-white">{{svg "octicon-circle-slash"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -122,8 +122,8 @@ | |||||||
| 	{{else if eq .Type 28}} | 	{{else if eq .Type 28}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge bg-purple text-white">{{svg "octicon-git-merge"}}</span> | 			<span class="badge bg-purple text-white">{{svg "octicon-git-merge"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -147,8 +147,8 @@ | |||||||
| 		{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }} | 		{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-bookmark"}}</span> | 			<span class="badge">{{svg "octicon-bookmark"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			{{if eq .RefAction 3}}<del>{{end}} | 			{{if eq .RefAction 3}}<del>{{end}} | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| @@ -164,8 +164,8 @@ | |||||||
| 	{{else if eq .Type 4}} | 	{{else if eq .Type 4}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-bookmark"}}</span> | 			<span class="badge">{{svg "octicon-bookmark"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -180,8 +180,8 @@ | |||||||
| 		{{if or .AddedLabels .RemovedLabels}} | 		{{if or .AddedLabels .RemovedLabels}} | ||||||
| 			<div class="timeline-item event" id="{{.HashTag}}"> | 			<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 				<span class="badge">{{svg "octicon-tag"}}</span> | 				<span class="badge">{{svg "octicon-tag"}}</span> | ||||||
| 				<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 				<a href="{{.Poster.HomeLink}}"> | ||||||
| 					<img src="{{.Poster.RelAvatarLink}}"> | 					{{avatar .Poster}} | ||||||
| 				</a> | 				</a> | ||||||
| 				<span class="text grey"> | 				<span class="text grey"> | ||||||
| 					<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 					<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -198,8 +198,8 @@ | |||||||
| 	{{else if eq .Type 8}} | 	{{else if eq .Type 8}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-milestone"}}</span> | 			<span class="badge">{{svg "octicon-milestone"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -211,8 +211,8 @@ | |||||||
| 			<span class="badge">{{svg "octicon-person"}}</span> | 			<span class="badge">{{svg "octicon-person"}}</span> | ||||||
| 			{{if gt .AssigneeID 0}} | 			{{if gt .AssigneeID 0}} | ||||||
| 				{{if .RemovedAssignee}} | 				{{if .RemovedAssignee}} | ||||||
| 					<a class="ui avatar image" href="{{.Assignee.HomeLink}}"> | 					<a href="{{.Assignee.HomeLink}}"> | ||||||
| 						<img src="{{.Assignee.RelAvatarLink}}"> | 						{{avatar .Assignee}} | ||||||
| 					</a> | 					</a> | ||||||
| 					<span class="text grey"> | 					<span class="text grey"> | ||||||
| 						<a class="author" href="{{.Assignee.HomeLink}}">{{.Assignee.GetDisplayName}}</a> | 						<a class="author" href="{{.Assignee.HomeLink}}">{{.Assignee.GetDisplayName}}</a> | ||||||
| @@ -223,8 +223,8 @@ | |||||||
| 						{{ end }} | 						{{ end }} | ||||||
| 					</span> | 					</span> | ||||||
| 				{{else}} | 				{{else}} | ||||||
| 					<a class="ui avatar image" href="{{.Assignee.HomeLink}}"> | 					<a href="{{.Assignee.HomeLink}}"> | ||||||
| 						<img src="{{.Assignee.RelAvatarLink}}"> | 						{{avatar .Assignee}} | ||||||
| 					</a> | 					</a> | ||||||
| 					<span class="text grey"> | 					<span class="text grey"> | ||||||
| 						<a class="author" href="{{.Assignee.HomeLink}}">{{.Assignee.GetDisplayName}}</a> | 						<a class="author" href="{{.Assignee.HomeLink}}">{{.Assignee.GetDisplayName}}</a> | ||||||
| @@ -240,8 +240,8 @@ | |||||||
| 	{{else if eq .Type 10}} | 	{{else if eq .Type 10}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-pencil"}}</span> | 			<span class="badge">{{svg "octicon-pencil"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -251,8 +251,8 @@ | |||||||
| 	{{else if eq .Type 11}} | 	{{else if eq .Type 11}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-git-branch"}}</span> | 			<span class="badge">{{svg "octicon-git-branch"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -262,8 +262,8 @@ | |||||||
| 	{{else if eq .Type 12}} | 	{{else if eq .Type 12}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -273,8 +273,8 @@ | |||||||
| 	{{else if eq .Type 13}} | 	{{else if eq .Type 13}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -288,8 +288,8 @@ | |||||||
| 	{{else if eq .Type 14}} | 	{{else if eq .Type 14}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -303,8 +303,8 @@ | |||||||
| 	{{else if eq .Type 15}} | 	{{else if eq .Type 15}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -314,8 +314,8 @@ | |||||||
| 	{{else if eq .Type 16}} | 	{{else if eq .Type 16}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -325,8 +325,8 @@ | |||||||
| 	{{else if eq .Type 17}} | 	{{else if eq .Type 17}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -336,8 +336,8 @@ | |||||||
| 	{{else if eq .Type 18}} | 	{{else if eq .Type 18}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -347,8 +347,8 @@ | |||||||
| 	{{else if eq .Type 19}} | 	{{else if eq .Type 19}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-package-dependents"}}</span> | 			<span class="badge">{{svg "octicon-package-dependents"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -372,8 +372,8 @@ | |||||||
| 	{{else if eq .Type 20}} | 	{{else if eq .Type 20}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-package-dependents"}}</span> | 			<span class="badge">{{svg "octicon-package-dependents"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -400,7 +400,7 @@ | |||||||
| 				{{if .OriginalAuthor }} | 				{{if .OriginalAuthor }} | ||||||
| 				{{else}} | 				{{else}} | ||||||
| 				<a class="timeline-avatar"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}> | 				<a class="timeline-avatar"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}> | ||||||
| 					<img src="{{.Poster.RelAvatarLink}}"> | 					{{avatar .Poster}} | ||||||
| 				</a> | 				</a> | ||||||
| 				{{end}} | 				{{end}} | ||||||
| 				<span class="badge {{if eq .Review.Type 1}}bg-green | 				<span class="badge {{if eq .Review.Type 1}}bg-green | ||||||
| @@ -509,7 +509,7 @@ | |||||||
| 											<div class="comment code-comment" id="{{.HashTag}}"> | 											<div class="comment code-comment" id="{{.HashTag}}"> | ||||||
| 												{{if not .OriginalAuthor }} | 												{{if not .OriginalAuthor }} | ||||||
| 													<a class="avatar"> | 													<a class="avatar"> | ||||||
| 														<img src="{{.Poster.RelAvatarLink}}"> | 														{{avatar .Poster}} | ||||||
| 													</a> | 													</a> | ||||||
| 												{{end}} | 												{{end}} | ||||||
| 												<div class="content"> | 												<div class="content"> | ||||||
| @@ -560,8 +560,8 @@ | |||||||
| 	{{else if eq .Type 23}} | 	{{else if eq .Type 23}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-lock"}}</span> | 			<span class="badge">{{svg "octicon-lock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			{{ if .Content }} | 			{{ if .Content }} | ||||||
| 				<span class="text grey"> | 				<span class="text grey"> | ||||||
| @@ -578,8 +578,8 @@ | |||||||
| 	{{else if eq .Type 24}} | 	{{else if eq .Type 24}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-key"}}</span> | 			<span class="badge">{{svg "octicon-key"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -589,8 +589,8 @@ | |||||||
| 	{{else if eq .Type 25}} | 	{{else if eq .Type 25}} | ||||||
| 		<div class="timeline-item event"> | 		<div class="timeline-item event"> | ||||||
| 			<span class="badge">{{svg "octicon-git-branch"}}</span> | 			<span class="badge">{{svg "octicon-git-branch"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> | 				<a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> | ||||||
| @@ -600,8 +600,8 @@ | |||||||
| 	{{else if eq .Type 26}} | 	{{else if eq .Type 26}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-clock"}}</span> | 			<span class="badge">{{svg "octicon-clock"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -615,8 +615,8 @@ | |||||||
| 	{{else if eq .Type 27}} | 	{{else if eq .Type 27}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-eye"}}</span> | 			<span class="badge">{{svg "octicon-eye"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
| @@ -658,8 +658,8 @@ | |||||||
| 		{{if not $.UnitProjectsGlobalDisabled}} | 		{{if not $.UnitProjectsGlobalDisabled}} | ||||||
| 		<div class="timeline-item event" id="{{.HashTag}}"> | 		<div class="timeline-item event" id="{{.HashTag}}"> | ||||||
| 			<span class="badge">{{svg "octicon-project"}}</span> | 			<span class="badge">{{svg "octicon-project"}}</span> | ||||||
| 			<a class="ui avatar image" href="{{.Poster.HomeLink}}"> | 			<a href="{{.Poster.HomeLink}}"> | ||||||
| 				<img src="{{.Poster.RelAvatarLink}}"> | 				{{avatar .Poster}} | ||||||
| 			</a> | 			</a> | ||||||
| 			<span class="text grey"> | 			<span class="text grey"> | ||||||
| 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | 				<a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> | ||||||
|   | |||||||
| @@ -9,8 +9,8 @@ | |||||||
| 					<div class="review-item"> | 					<div class="review-item"> | ||||||
| 						<div class="review-item-left"> | 						<div class="review-item-left"> | ||||||
| 							{{if .User}} | 							{{if .User}} | ||||||
| 								<a class="ui avatar image" href="{{.User.HomeLink}}"> | 								<a href="{{.User.HomeLink}}"> | ||||||
| 									<img src="{{.User.RelAvatarLink}}"> | 									{{avatar .User}} | ||||||
| 								</a> | 								</a> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 							<span class="text grey"> | 							<span class="text grey"> | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ | |||||||
| 							<a class="{{if not .CanChange}}ui poping up{{end}} item {{if .Checked}} checked {{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_{{.ItemID}}" {{if not .CanChange}} data-content="{{$.i18n.Tr "repo.issues.remove_request_review_block"}}"{{end}}> | 							<a class="{{if not .CanChange}}ui poping up{{end}} item {{if .Checked}} checked {{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_{{.ItemID}}" {{if not .CanChange}} data-content="{{$.i18n.Tr "repo.issues.remove_request_review_block"}}"{{end}}> | ||||||
| 								<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check"}}</span> | 								<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check"}}</span> | ||||||
| 								<span class="text"> | 								<span class="text"> | ||||||
| 									<img class="ui avatar image mr-2" loading="lazy" src="{{.User.RelAvatarLink}}"> | 									{{avatar .User 28 "mr-3"}} | ||||||
| 									{{.User.GetDisplayName}} | 									{{.User.GetDisplayName}} | ||||||
| 								</span> | 								</span> | ||||||
| 							</a> | 							</a> | ||||||
| @@ -56,7 +56,7 @@ | |||||||
| 					<div class="item mb-2"> | 					<div class="item mb-2"> | ||||||
| 						{{if .User}} | 						{{if .User}} | ||||||
| 							<a class="muted sidebar-item-link" href="{{.User.HomeLink}}"> | 							<a class="muted sidebar-item-link" href="{{.User.HomeLink}}"> | ||||||
| 								<img class="ui avatar image mr-3" src="{{.User.RelAvatarLink}}"> | 								{{avatar .User 28 "mr-3"}} | ||||||
| 								{{.User.GetDisplayName}} | 								{{.User.GetDisplayName}} | ||||||
| 							</a> | 							</a> | ||||||
| 						{{else if .Team}} | 						{{else if .Team}} | ||||||
| @@ -267,7 +267,7 @@ | |||||||
| 						{{end}} | 						{{end}} | ||||||
| 						<span class="octicon-check {{if not $checked}}invisible{{end}}">{{svg "octicon-check"}}</span> | 						<span class="octicon-check {{if not $checked}}invisible{{end}}">{{svg "octicon-check"}}</span> | ||||||
| 						<span class="text"> | 						<span class="text"> | ||||||
| 							<img class="ui avatar image mr-2" loading="lazy" src="{{.RelAvatarLink}}"> | 							{{avatar . 28 "mr-3"}} | ||||||
| 							{{.GetDisplayName}} | 							{{.GetDisplayName}} | ||||||
| 						</span> | 						</span> | ||||||
| 					</a> | 					</a> | ||||||
| @@ -280,7 +280,7 @@ | |||||||
| 				{{range .Issue.Assignees}} | 				{{range .Issue.Assignees}} | ||||||
| 					<div class="item"> | 					<div class="item"> | ||||||
| 						<a class="muted sidebar-item-link" href="{{$.RepoLink}}/{{if $.Issue.IsPull}}pulls{{else}}issues{{end}}?assignee={{.ID}}"> | 						<a class="muted sidebar-item-link" href="{{$.RepoLink}}/{{if $.Issue.IsPull}}pulls{{else}}issues{{end}}?assignee={{.ID}}"> | ||||||
| 							<img class="ui avatar image mr-3" src="{{.RelAvatarLink}}"> | 							{{avatar . 28 "mr-3"}} | ||||||
| 							{{.GetDisplayName}} | 							{{.GetDisplayName}} | ||||||
| 						</a> | 						</a> | ||||||
| 					</div> | 					</div> | ||||||
| @@ -295,7 +295,9 @@ | |||||||
| 			<div> | 			<div> | ||||||
| 				{{range .Participants}} | 				{{range .Participants}} | ||||||
| 					<a {{if gt .ID 0}}href="{{.HomeLink}}"{{end}}> | 					<a {{if gt .ID 0}}href="{{.HomeLink}}"{{end}}> | ||||||
| 						<img class="ui avatar image poping up" src="{{.RelAvatarLink}}" data-content="{{.GetDisplayName}}" data-position="top center" data-variation="small inverted"> | 						<div class="ui poping up" data-content="{{.GetDisplayName}}" data-position="top center" data-variation="small inverted"> | ||||||
|  | 							{{avatar .}} | ||||||
|  | 						</div> | ||||||
| 					</a> | 					</a> | ||||||
| 				{{end}} | 				{{end}} | ||||||
| 			</div> | 			</div> | ||||||
| @@ -376,7 +378,7 @@ | |||||||
| 						{{range $user, $trackedtime := .WorkingUsers}} | 						{{range $user, $trackedtime := .WorkingUsers}} | ||||||
| 							<div class="comment"> | 							<div class="comment"> | ||||||
| 								<a class="avatar"> | 								<a class="avatar"> | ||||||
| 									<img src="{{$user.RelAvatarLink}}"> | 									{{avatar $user}} | ||||||
| 								</a> | 								</a> | ||||||
| 								<div class="content"> | 								<div class="content"> | ||||||
| 									<a class="author">{{$user.DisplayName}}</a> | 									<a class="author">{{$user.DisplayName}}</a> | ||||||
|   | |||||||
| @@ -48,18 +48,18 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu" title="{{.SignedUser.Name}}"> | 							<div class="menu" title="{{.SignedUser.Name}}"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 									{{avatar .SignedUser}} | ||||||
| 									{{.SignedUser.ShortName 20}} | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar .}} | ||||||
| 										{{.ShortName 20}} | 										{{.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -82,18 +82,18 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu" title="{{.SignedUser.Name}}"> | 							<div class="menu" title="{{.SignedUser.Name}}"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 									{{avatar .SignedUser}} | ||||||
| 									{{.SignedUser.ShortName 20}} | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 								<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 								<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 									<img class="ui mini image" src="{{.RelAvatarLink}}"> | 									{{avatar .}} | ||||||
| 									{{.ShortName 20}} | 									{{.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -82,18 +82,18 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser 28 "mini"}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu" title="{{.SignedUser.Name}}"> | 							<div class="menu" title="{{.SignedUser.Name}}"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 									{{avatar .SignedUser 28 "mini"}} | ||||||
| 									{{.SignedUser.ShortName 20}} | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 										{{.ShortName 20}} | 										{{.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -82,18 +82,18 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser 28 "mini"}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu" title="{{.SignedUser.Name}}"> | 							<div class="menu" title="{{.SignedUser.Name}}"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 									{{avatar .SignedUser 28 "mini"}} | ||||||
| 									{{.SignedUser.ShortName 20}} | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 										{{.ShortName 20}} | 										{{.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -78,7 +78,6 @@ | |||||||
| 					{{if and $.CanWriteProjects (not $.Repository.IsArchived) $.PageIsProjects (ne .ID 0)}} | 					{{if and $.CanWriteProjects (not $.Repository.IsArchived) $.PageIsProjects (ne .ID 0)}} | ||||||
| 						<div class="ui dropdown jump item poping up right" data-variation="tiny inverted"> | 						<div class="ui dropdown jump item poping up right" data-variation="tiny inverted"> | ||||||
| 							<span class="ui text"> | 							<span class="ui text"> | ||||||
| 								<img class="ui tiny avatar image" width="24" height="24"> |  | ||||||
| 								<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-kebab-horizontal" 24}}</span> | 								<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-kebab-horizontal" 24}}</span> | ||||||
| 							</span> | 							</span> | ||||||
| 							<div class="menu user-menu" tabindex="-1"> | 							<div class="menu user-menu" tabindex="-1"> | ||||||
|   | |||||||
| @@ -14,20 +14,20 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser 28 "mini"}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu"> | 							<div class="menu"> | ||||||
| 								{{if .CanForkToUser}} | 								{{if .CanForkToUser}} | ||||||
| 									<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | 									<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | 										{{avatar .SignedUser 28 "mini"}} | ||||||
| 										{{.SignedUser.ShortName 20}} | 										{{.SignedUser.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 									<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 										{{.ShortName 20}} | 										{{.ShortName 20}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -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"> | ||||||
| 									<img class="img-10" src="{{.Publisher.RelAvatarLink}}"> | 									{{avatar .Publisher 28 "img-10"}} | ||||||
| 									<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}} | ||||||
| 									<img class="img-10" src="{{.Publisher.RelAvatarLink}}"> | 									{{avatar .Publisher 28 "img-10"}} | ||||||
| 									<a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.GetDisplayName}}</a> | 									<a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.GetDisplayName}}</a> | ||||||
| 								{{else}} | 								{{else}} | ||||||
| 									Ghost | 									Ghost | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
| 				<div class="item ui grid"> | 				<div class="item ui grid"> | ||||||
| 					<div class="ui five wide column"> | 					<div class="ui five wide column"> | ||||||
| 						<a href="{{AppSubUrl}}/{{.Name}}"> | 						<a href="{{AppSubUrl}}/{{.Name}}"> | ||||||
| 							<img class="ui avatar image" src="{{.RelAvatarLink}}"> | 							{{avatar .}} | ||||||
| 							{{.DisplayName}} | 							{{.DisplayName}} | ||||||
| 						</a> | 						</a> | ||||||
| 					</div> | 					</div> | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ | |||||||
| 							</td> | 							</td> | ||||||
| 							<td> | 							<td> | ||||||
| 								<a href="{{AppSubUrl}}/{{$lock.Owner.Name}}"> | 								<a href="{{AppSubUrl}}/{{$lock.Owner.Name}}"> | ||||||
| 									<img class="ui avatar image" src="{{$lock.Owner.RelAvatarLink}}"> | 									{{avatar $lock.Owner}} | ||||||
| 									{{$lock.Owner.DisplayName}} | 									{{$lock.Owner.DisplayName}} | ||||||
| 								</a> | 								</a> | ||||||
| 							</td> | 							</td> | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ | |||||||
| 								<div class="menu"> | 								<div class="menu"> | ||||||
| 									{{range .Users}} | 									{{range .Users}} | ||||||
| 										<div class="item" data-value="{{.ID}}"> | 										<div class="item" data-value="{{.ID}}"> | ||||||
| 											<img class="ui mini image" src="{{.RelAvatarLink}}"> | 											{{avatar . 28 "mini"}} | ||||||
| 											{{.GetDisplayName}} | 											{{.GetDisplayName}} | ||||||
| 										</div> | 										</div> | ||||||
| 									{{end}} | 									{{end}} | ||||||
| @@ -98,7 +98,7 @@ | |||||||
| 								<div class="menu"> | 								<div class="menu"> | ||||||
| 								{{range .Users}} | 								{{range .Users}} | ||||||
| 									<div class="item" data-value="{{.ID}}"> | 									<div class="item" data-value="{{.ID}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 									{{.GetDisplayName}} | 									{{.GetDisplayName}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
| @@ -178,7 +178,7 @@ | |||||||
| 								<div class="menu"> | 								<div class="menu"> | ||||||
| 								{{range .Users}} | 								{{range .Users}} | ||||||
| 									<div class="item" data-value="{{.ID}}"> | 									<div class="item" data-value="{{.ID}}"> | ||||||
| 										<img class="ui mini image" src="{{.RelAvatarLink}}"> | 										{{avatar . 28 "mini"}} | ||||||
| 									{{.GetDisplayName}} | 									{{.GetDisplayName}} | ||||||
| 									</div> | 									</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ | |||||||
| 		<div title="{{if eq .verification.TrustStatus "trusted"}}{{else if eq .verification.TrustStatus "untrusted"}}{{$.root.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{$.root.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.verification.Reason}}"> | 		<div title="{{if eq .verification.TrustStatus "trusted"}}{{else if eq .verification.TrustStatus "untrusted"}}{{$.root.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{$.root.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.verification.Reason}}"> | ||||||
| 		{{if ne .verification.SigningUser.ID 0}} | 		{{if ne .verification.SigningUser.ID 0}} | ||||||
| 			{{svg "gitea-lock"}} | 			{{svg "gitea-lock"}} | ||||||
| 			<img class="ui signature avatar image" src="{{.verification.SigningUser.RelAvatarLink}}" /> | 			{{avatar .verification.SigningUser "signature"}} | ||||||
| 		{{else}} | 		{{else}} | ||||||
| 			<span title="{{$.root.i18n.Tr "gpg.default_key"}}">{{svg "gitea-lock-cog"}}</span> | 			<span title="{{$.root.i18n.Tr "gpg.default_key"}}">{{svg "gitea-lock-cog"}}</span> | ||||||
| 			<img class="ui signature avatar image" src="{{AvatarLink .verification.SigningEmail}}" /> | 			{{avatarByEmail .verification.SigningEmail "" 28 "signature"}} | ||||||
| 		{{end}} | 		{{end}} | ||||||
| 		</div> | 		</div> | ||||||
| 	{{else}} | 	{{else}} | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 		{{range .Cards}} | 		{{range .Cards}} | ||||||
| 			<li class="item ui segment"> | 			<li class="item ui segment"> | ||||||
| 				<a href="{{.HomeLink}}"> | 				<a href="{{.HomeLink}}"> | ||||||
| 					<img class="avatar" src="{{.RelAvatarLink}}"/> | 					{{avatar .}} | ||||||
| 				</a> | 				</a> | ||||||
| 				<h3 class="name"><a href="{{.HomeLink}}">{{.DisplayName}}</a></h3> | 				<h3 class="name"><a href="{{.HomeLink}}">{{.DisplayName}}</a></h3> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| 		<tr class="commit-list"> | 		<tr class="commit-list"> | ||||||
| 			<th colspan="2"> | 			<th colspan="2"> | ||||||
| 				{{if .LatestCommitUser}} | 				{{if .LatestCommitUser}} | ||||||
| 					<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" /> | 					{{avatar .LatestCommitUser 28 "img-12"}} | ||||||
| 					{{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}} | ||||||
| 						<img class="ui avatar image img-12" src="{{AvatarLink .LatestCommit.Author.Email}}" /> | 						{{avatarByEmail .LatestCommit.Author.Email .LatestCommit.Author.Name 28 "img-12"}} | ||||||
| 						<strong>{{.LatestCommit.Author.Name}}</strong> | 						<strong>{{.LatestCommit.Author.Name}}</strong> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 				{{end}} | 				{{end}} | ||||||
|   | |||||||
| @@ -121,7 +121,7 @@ | |||||||
| 				<div class="issue-item-icon-right text grey"> | 				<div class="issue-item-icon-right text grey"> | ||||||
| 					{{range .Assignees}} | 					{{range .Assignees}} | ||||||
| 						<a class="ui assignee poping up" href="{{.HomeLink}}" data-content="{{.GetDisplayName}}" data-variation="inverted" data-position="left center"> | 						<a class="ui assignee poping up" href="{{.HomeLink}}" data-content="{{.GetDisplayName}}" data-variation="inverted" data-position="left center"> | ||||||
| 							<img class="ui avatar image" src="{{.RelAvatarLink}}"> | 							{{avatar .}} | ||||||
| 						</a> | 						</a> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 				</div> | 				</div> | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| {{range .Feeds}} | {{range .Feeds}} | ||||||
| 	<div class="news"> | 	<div class="news"> | ||||||
| 		<div class="ui left"> | 		<div class="ui left"> | ||||||
| 			<img class="ui avatar image" src="{{.GetActAvatar}}" alt=""> | 			{{avatar .ActUser}} | ||||||
| 		</div> | 		</div> | ||||||
| 		<div class="ui grid"> | 		<div class="ui grid"> | ||||||
| 			<div class="ui fourteen wide column"> | 			<div class="ui fourteen wide column"> | ||||||
| @@ -84,7 +84,13 @@ | |||||||
| 								{{if $push.Commits}} | 								{{if $push.Commits}} | ||||||
| 									{{range $push.Commits}} | 									{{range $push.Commits}} | ||||||
| 										{{ $commitLink := printf "%s/commit/%s" $repoLink .Sha1}} | 										{{ $commitLink := printf "%s/commit/%s" $repoLink .Sha1}} | ||||||
| 										<li><img class="img-8" src="{{$push.AvatarLink .AuthorEmail}}"> <a class="commit-id" href="{{$commitLink}}">{{ShortSha .Sha1}}</a> <span class="text truncate light grey">{{RenderCommitMessage .Message $repoLink $.ComposeMetas}}</span></li> | 										<li> | ||||||
|  | 											{{avatarByEmail .AuthorEmail .AuthorName 28 "img-8 mr-2"}} | ||||||
|  | 											<a class="commit-id mr-2" href="{{$commitLink}}">{{ShortSha .Sha1}}</a> | ||||||
|  | 											<span class="text truncate light grey"> | ||||||
|  | 												{{RenderCommitMessage .Message $repoLink $.ComposeMetas}} | ||||||
|  | 											</span> | ||||||
|  | 										</li> | ||||||
| 									{{end}} | 									{{end}} | ||||||
| 								{{end}} | 								{{end}} | ||||||
| 								{{if and (gt $push.Len 1) $push.CompareURL}}<li><a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{$.i18n.Tr "action.compare_commits" $push.Len}} »</a></li>{{end}} | 								{{if and (gt $push.Len 1) $push.CompareURL}}<li><a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{$.i18n.Tr "action.compare_commits" $push.Len}} »</a></li>{{end}} | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| 		<div class="item"> | 		<div class="item"> | ||||||
| 			<div class="ui floating dropdown link jump"> | 			<div class="ui floating dropdown link jump"> | ||||||
| 				<span class="text"> | 				<span class="text"> | ||||||
| 					<img class="ui avatar image" src="{{.ContextUser.RelAvatarLink}}" title="{{.ContextUser.Name}}" width="28" height="28"> | 					{{avatar .ContextUser}} | ||||||
| 					{{.ContextUser.ShortName 20}} | 					{{.ContextUser.ShortName 20}} | ||||||
| 					{{if .ContextUser.IsOrganization}} | 					{{if .ContextUser.IsOrganization}} | ||||||
| 						<span class="org-visibility"> | 						<span class="org-visibility"> | ||||||
| @@ -19,12 +19,11 @@ | |||||||
| 					</div> | 					</div> | ||||||
| 					<div class="scrolling menu items"> | 					<div class="scrolling menu items"> | ||||||
| 						<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{else if .PageIsMilestonesDashboard}}milestones{{end}}"> | 						<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{else if .PageIsMilestonesDashboard}}milestones{{end}}"> | ||||||
| 							<img class="ui avatar image" src="{{.SignedUser.RelAvatarLink}}" width="28" height="28"> | 							{{avatar .SignedUser}} | ||||||
| 							{{.SignedUser.Name}} |  | ||||||
| 						</a> | 						</a> | ||||||
| 						{{range .Orgs}} | 						{{range .Orgs}} | ||||||
| 							<a class="{{if eq $.ContextUser.ID .ID}}active selected{{end}} item" title="{{.Name}}" href="{{AppSubUrl}}/org/{{.Name}}/{{if $.PageIsIssues}}issues{{else if $.PageIsPulls}}pulls{{else if $.PageIsMilestonesDashboard}}milestones{{else}}dashboard{{end}}"> | 							<a class="{{if eq $.ContextUser.ID .ID}}active selected{{end}} item" title="{{.Name}}" href="{{AppSubUrl}}/org/{{.Name}}/{{if $.PageIsIssues}}issues{{else if $.PageIsPulls}}pulls{{else if $.PageIsMilestonesDashboard}}milestones{{else}}dashboard{{end}}"> | ||||||
| 								<img class="ui avatar image" src="{{.RelAvatarLink}}" width="28" height="28"> | 								{{avatar .}} | ||||||
| 								{{.ShortName 20}} | 								{{.ShortName 20}} | ||||||
| 								<span class="org-visibility"> | 								<span class="org-visibility"> | ||||||
| 									{{if .Visibility.IsLimited}}<div class="ui orange tiny horizontal label">{{$.i18n.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | 									{{if .Visibility.IsLimited}}<div class="ui orange tiny horizontal label">{{$.i18n.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}} | ||||||
|   | |||||||
| @@ -6,19 +6,19 @@ | |||||||
| 				<div class="ui card"> | 				<div class="ui card"> | ||||||
| 					{{if eq .SignedUserName .Owner.Name}} | 					{{if eq .SignedUserName .Owner.Name}} | ||||||
| 						<a class="image poping up" href="{{AppSubUrl}}/user/settings" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center"> | 						<a class="image poping up" href="{{AppSubUrl}}/user/settings" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center"> | ||||||
| 							<img src="{{.Owner.SizedRelAvatarLink 290}}" title="{{.Owner.Name}}" height="290" width="290"/> | 							{{avatar .Owner 290}} | ||||||
| 						</a> | 						</a> | ||||||
| 					{{else}} | 					{{else}} | ||||||
| 						<span class="image"> | 						<span class="image" id="profile-avatar"> | ||||||
| 							<img src="{{.Owner.SizedRelAvatarLink 290}}" title="{{.Owner.Name}}" height="290" width="290"/> | 							{{avatar .Owner 290}} | ||||||
| 						</span> | 						</span> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 					<div class="content word-break"> | 					<div class="content word-break profile-avatar-name"> | ||||||
| 						{{if .Owner.FullName}}<span class="header text center">{{.Owner.FullName}}</span>{{end}} | 						{{if .Owner.FullName}}<span class="header text center">{{.Owner.FullName}}</span>{{end}} | ||||||
| 						<span class="username text center">{{.Owner.Name}}</span> | 						<span class="username text center">{{.Owner.Name}}</span> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div class="extra content word-break"> | 					<div class="extra content word-break"> | ||||||
| 						<ul class="text black"> | 						<ul> | ||||||
| 							{{if .Owner.Location}} | 							{{if .Owner.Location}} | ||||||
| 								<li>{{svg "octicon-location"}} {{.Owner.Location}}</li> | 								<li>{{svg "octicon-location"}} {{.Owner.Location}}</li> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -54,7 +54,9 @@ | |||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 									{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.HasMemberWithUserID $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | 									{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.HasMemberWithUserID $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | ||||||
| 									<li> | 									<li> | ||||||
| 										<a href="{{.HomeLink}}"><img class="ui image poping up" src="{{.RelAvatarLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted"></a> | 										<a class="poping up" href="{{.HomeLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted"> | ||||||
|  | 											{{avatar .}} | ||||||
|  | 										</a> | ||||||
| 									</li> | 									</li> | ||||||
| 									{{end}} | 									{{end}} | ||||||
| 								{{end}} | 								{{end}} | ||||||
|   | |||||||
| @@ -14,17 +14,19 @@ | |||||||
| 						<div class="ui selection owner dropdown"> | 						<div class="ui selection owner dropdown"> | ||||||
| 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | 							<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | ||||||
| 							<span class="text" title="{{.ContextUser.Name}}"> | 							<span class="text" title="{{.ContextUser.Name}}"> | ||||||
| 								<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | 								{{avatar .ContextUser 28 "mini"}} | ||||||
| 								{{.ContextUser.ShortName 20}} | 								{{.ContextUser.ShortName 20}} | ||||||
| 							</span> | 							</span> | ||||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||||
| 							<div class="menu"> | 							<div class="menu"> | ||||||
| 								<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | 								<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | ||||||
| 									<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> {{.SignedUser.ShortName 20}} | 									{{avatar .SignedUser 28 "mini"}} | ||||||
|  | 									{{.SignedUser.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{range .Orgs}} | 								{{range .Orgs}} | ||||||
| 								<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | 								<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | ||||||
| 									<img class="ui mini image" src="{{.RelAvatarLink}}"> {{.ShortName 20}} | 									{{avatar . 28 "mini"}} | ||||||
|  | 									{{.ShortName 20}} | ||||||
| 								</div> | 								</div> | ||||||
| 								{{end}} | 								{{end}} | ||||||
| 							</div> | 							</div> | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ | |||||||
| 								<button type="submit" class="ui blue small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.leave"}}</button> | 								<button type="submit" class="ui blue small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.leave"}}</button> | ||||||
| 							</form> | 							</form> | ||||||
| 						</div> | 						</div> | ||||||
| 						<img class="ui mini image" src="{{.RelAvatarLink}}"> | 						{{avatar . 28 "mini"}} | ||||||
| 						<div class="content"> | 						<div class="content"> | ||||||
| 								<a href="{{.HomeLink}}">{{.Name}}</a> | 								<a href="{{.HomeLink}}">{{.Name}}</a> | ||||||
| 						</div> | 						</div> | ||||||
|   | |||||||
| @@ -410,6 +410,19 @@ a.muted:hover, | |||||||
|   border-color: var(--color-secondary); |   border-color: var(--color-secondary); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .ui.avatar.images .image, | ||||||
|  | .ui.avatar.images img, | ||||||
|  | .ui.avatar.images svg, | ||||||
|  | .ui.avatar.image img, | ||||||
|  | .ui.avatar.image svg, | ||||||
|  | .ui.avatar.image, | ||||||
|  | .ui.cards > .card img.avatar, | ||||||
|  | .ui.cards > .card .avatar img, | ||||||
|  | .ui.card img.avatar, | ||||||
|  | .ui.card .avatar img { | ||||||
|  |   border-radius: var(--border-radius); | ||||||
|  | } | ||||||
|  |  | ||||||
| .dont-break-out { | .dont-break-out { | ||||||
|   overflow-wrap: break-word; |   overflow-wrap: break-word; | ||||||
|   word-wrap: break-word; |   word-wrap: break-word; | ||||||
| @@ -791,15 +804,6 @@ a.muted:hover, | |||||||
|     font-weight: normal; |     font-weight: normal; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .avatar.image, |  | ||||||
|   .avatar.image img, |  | ||||||
|   .avatar.image svg, |  | ||||||
|   .avatar.images .image, |  | ||||||
|   .avatar.images img, |  | ||||||
|   .avatar.images svg { |  | ||||||
|     border-radius: 3px; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .form { |   .form { | ||||||
|     .fake { |     .fake { | ||||||
|       display: none !important; |       display: none !important; | ||||||
| @@ -1559,6 +1563,11 @@ a.ui.label:hover { | |||||||
|   margin-bottom: .4em; |   margin-bottom: .4em; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .ui.cards > .card > .extra, | ||||||
|  | .ui.card > .extra { | ||||||
|  |   color: var(--color-text); | ||||||
|  | } | ||||||
|  |  | ||||||
| .color-icon { | .color-icon { | ||||||
|   margin-right: .5em; |   margin-right: .5em; | ||||||
|   margin-left: .5em; |   margin-left: .5em; | ||||||
|   | |||||||
| @@ -100,7 +100,7 @@ | |||||||
|       margin-right: auto; |       margin-right: auto; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     .ui.avatar { |     .left .ui.avatar { | ||||||
|       margin-top: 13px; |       margin-top: 13px; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,13 +34,15 @@ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   &.profile { |   &.profile { | ||||||
|     #org-avatar { |     .org-avatar { | ||||||
|       width: 100px; |       width: 100px; | ||||||
|       height: 100px; |       height: 100px; | ||||||
|       margin-right: 15px; |       margin-right: 15px; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #org-info { |     #org-info { | ||||||
|  |       overflow-wrap: anywhere; | ||||||
|  |  | ||||||
|       .ui.header { |       .ui.header { | ||||||
|         font-size: 36px; |         font-size: 36px; | ||||||
|         margin-bottom: 0; |         margin-bottom: 0; | ||||||
|   | |||||||
| @@ -826,8 +826,8 @@ | |||||||
|           position: absolute; |           position: absolute; | ||||||
|           left: -72px; |           left: -72px; | ||||||
|           img { |           img { | ||||||
|             width: 40px; |             width: 40px !important; | ||||||
|             height: 40px; |             height: 40px !important; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,6 +15,10 @@ | |||||||
|         line-height: 1.3rem; |         line-height: 1.3rem; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       .profile-avatar-name { | ||||||
|  |         border-top: none; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       .extra.content { |       .extra.content { | ||||||
|         padding: 0; |         padding: 0; | ||||||
|  |  | ||||||
| @@ -46,9 +50,16 @@ | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       #profile-avatar { |       #profile-avatar { | ||||||
|  |         background: none; | ||||||
|  |         padding: 1rem 1rem .25rem; | ||||||
|  |  | ||||||
|         img { |         img { | ||||||
|           width: 100%; |           width: 100%; | ||||||
|  |           height: auto; | ||||||
|  |           object-fit: contain; | ||||||
|  |           margin: 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         @media @mediaSm { |         @media @mediaSm { | ||||||
|           height: 250px; |           height: 250px; | ||||||
|           overflow: hidden; |           overflow: hidden; | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| .fc { flex-direction: column !important; } | .fc { flex-direction: column !important; } | ||||||
| .f1 { flex: 1 !important; } | .f1 { flex: 1 !important; } | ||||||
| .fw { flex-wrap: wrap !important; } | .fw { flex-wrap: wrap !important; } | ||||||
|  | .vm { vertical-align: middle !important; } | ||||||
|  |  | ||||||
| .mono { | .mono { | ||||||
|   font-family: var(--fonts-monospace) !important; |   font-family: var(--fonts-monospace) !important; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user