From 303fa37b608a4925f5a0137c89e20a906b3d9fdb Mon Sep 17 00:00:00 2001 From: Sergey Dryabzhinsky Date: Sun, 17 Jun 2018 15:21:52 +0300 Subject: repo: support avatars (#5221) * First code for repository avatars * Last code for repository avatars - add new option for repo avatars location on filesystem - add route catch in web - add new fields to repo model - add migration - update settings handlers - update repo header template * Update locale messages * Add repo avatars to home page * Add repo avatars to organization right panel * Show repo avatars in repo list * Remove AvatarEamil field, remove Gravatar support, use generic locale messages * Fix migration * Fix seed and not used tool * Revert public css changes, add them to less files * Latest lessc (2.6.0) don't put result into file but output to stdout So redirect output to file * Simplify things: - migration don't needed, and table changes too - just upload file to repo avatar storage - or generate random image * Fix repo image seed - name not unique * Get rid of not needed model fields * Class value is enough, remove height attribute * Don't generate random avatar for repository - use html and semantic ui icons if no avatar found * Update styles and templates for repo - use repo icon as default avatar - use globe icon for public repos - add micro style for repo avatars at dashboard * Remvoe redundant empty line * Fix nl2br filter - must return string * Fix css style for micro-repo-avatar in dashboard list * Remove `|len`, works fine w/o it. * Update after review 2: - use static route for repository avatar - format images settings block in settings * Update after review 2: - no random avatar for repo * Update after review 2: - no random avatar for repo 2 - update imports - update UploadAvatar* functions * Update after review 2: - update templates * Fix trace call * Remove unused immport since we use static route for repo avatars. --- models/repo.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'models') diff --git a/models/repo.go b/models/repo.go index b15b0175..3a9f388b 100644 --- a/models/repo.go +++ b/models/repo.go @@ -15,10 +15,14 @@ import ( "sort" "strings" "time" + "image" + _ "image/jpeg" + "image/png" "github.com/Unknwon/cae/zip" "github.com/Unknwon/com" "github.com/go-xorm/xorm" + "github.com/nfnt/resize" "github.com/mcuadros/go-version" log "gopkg.in/clog.v1" "gopkg.in/ini.v1" @@ -27,6 +31,7 @@ import ( api "github.com/gogs/go-gogs-client" "github.com/gogs/gogs/models/errors" + "github.com/gogs/gogs/pkg/avatar" "github.com/gogs/gogs/pkg/bindata" "github.com/gogs/gogs/pkg/markup" "github.com/gogs/gogs/pkg/process" @@ -284,6 +289,61 @@ func (repo *Repository) HTMLURL() string { return setting.AppURL + repo.FullName() } +// CustomAvatarPath returns repository custom avatar file path. +func (repo *Repository) CustomAvatarPath() string { + return filepath.Join(setting.RepositoryAvatarUploadPath, com.ToStr(repo.ID)) +} + +// RelAvatarLink returns relative avatar link to the site domain, +// which includes app sub-url as prefix. +// Since Gravatar support not needed here - just check for image path. +func (repo *Repository) RelAvatarLink() string { + defaultImgUrl := "" + if !com.IsExist(repo.CustomAvatarPath()) { + return defaultImgUrl + } + return setting.AppSubURL + "/repo-avatars/" + com.ToStr(repo.ID) +} + +// AvatarLink returns user avatar absolute link. +func (repo *Repository) AvatarLink() string { + link := repo.RelAvatarLink() + if link[0] == '/' && link[1] != '/' { + return setting.AppURL + strings.TrimPrefix(link, setting.AppSubURL)[1:] + } + return link +} + +// UploadAvatar saves custom avatar for repository. +// FIXME: split uploads to different subdirs +// in case we have massive number of repositories. +func (repo *Repository) UploadAvatar(data []byte) error { + img, _, err := image.Decode(bytes.NewReader(data)) + if err != nil { + return fmt.Errorf("Decode: %v", err) + } + + m := resize.Resize(avatar.AVATAR_SIZE, avatar.AVATAR_SIZE, img, resize.NearestNeighbor) + os.MkdirAll(setting.RepositoryAvatarUploadPath, os.ModePerm) + fw, err := os.Create(repo.CustomAvatarPath()) + if err != nil { + return fmt.Errorf("Create: %v", err) + } + defer fw.Close() + + if err = png.Encode(fw, m); err != nil { + return fmt.Errorf("Encode: %v", err) + } + + return nil +} + +// DeleteAvatar deletes the repository custom avatar. +func (repo *Repository) DeleteAvatar() error { + log.Trace("DeleteAvatar [%d]: %s", repo.ID, repo.CustomAvatarPath()) + return os.Remove(repo.CustomAvatarPath()) +} + // This method assumes following fields have been assigned with valid values: // Required - BaseRepo (if fork) // Arguments that are allowed to be nil: permission @@ -312,6 +372,8 @@ func (repo *Repository) APIFormat(permission *api.Permission, user ...*User) *ap Created: repo.Created, Updated: repo.Updated, Permissions: permission, +// Reserved for go-gogs-client change +// AvatarUrl: repo.AvatarLink(), } if repo.IsFork { p := &api.Permission{Pull: true} -- cgit v1.2.3