Improve avatar uploading / resizing / compressing, remove Fomantic card module (#24653)

Fixes: #8972
Fixes: #24263

And I think it also (partially) fix #24263 (no need to convert) ,
because users could upload any supported image format if it isn't larger
than AVATAR_MAX_ORIGIN_SIZE


The main idea: 

* if the uploaded file size is not larger than AVATAR_MAX_ORIGIN_SIZE,
use the origin
* if the resized size is larger than the origin, use the origin

Screenshots:

JPG:

<details>


![image](70e98bb0-ecb9-4c4e-a89f-4a37d4e37f8e)

</details>

APNG:

<details>


![image](9055135b-5e2d-4152-bd72-596fcb7c6671)


![image](50364caf-f7f6-4241-a289-e485fe4cd582)

</details>

WebP (animated)

<details>


![image](f642eb85-498a-49a5-86bf-0a7b04089ae0)

</details>

The only exception: if a WebP image is larger than MaxOriginSize and it
is animated, then current `webp` package can't decode it, so only in
this case it isn't supported. IMO no need to support such case: why a
user would upload a 1MB animated webp as avatar? crazy .....

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
wxiaoguang 2023-05-14 02:59:11 +08:00 committed by GitHub
parent 9f1d377b87
commit 82224c54e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 304 additions and 1505 deletions

View file

@ -6,7 +6,6 @@ package repository
import (
"context"
"fmt"
"image/png"
"io"
"strconv"
"strings"
@ -21,7 +20,7 @@ import (
// UploadAvatar saves custom avatar for repository.
// FIXME: split uploads to different subdirs in case we have massive number of repos.
func UploadAvatar(ctx context.Context, repo *repo_model.Repository, data []byte) error {
m, err := avatar.Prepare(data)
avatarData, err := avatar.ProcessAvatarImage(data)
if err != nil {
return err
}
@ -47,9 +46,7 @@ func UploadAvatar(ctx context.Context, repo *repo_model.Repository, data []byte)
}
if err := storage.SaveFrom(storage.RepoAvatars, repo.CustomAvatarRelativePath(), func(w io.Writer) error {
if err := png.Encode(w, *m); err != nil {
log.Error("Encode: %v", err)
}
_, err := w.Write(avatarData)
return err
}); err != nil {
return fmt.Errorf("UploadAvatar %s failed: Failed to remove old repo avatar %s: %w", repo.RepoPath(), newAvatar, err)

View file

@ -6,7 +6,6 @@ package user
import (
"context"
"fmt"
"image/png"
"io"
"time"
@ -244,7 +243,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error {
// UploadAvatar saves custom avatar for user.
func UploadAvatar(u *user_model.User, data []byte) error {
m, err := avatar.Prepare(data)
avatarData, err := avatar.ProcessAvatarImage(data)
if err != nil {
return err
}
@ -262,9 +261,7 @@ func UploadAvatar(u *user_model.User, data []byte) error {
}
if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
if err := png.Encode(w, *m); err != nil {
log.Error("Encode: %v", err)
}
_, err := w.Write(avatarData)
return err
}); err != nil {
return fmt.Errorf("Failed to create dir %s: %w", u.CustomAvatarRelativePath(), err)