// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
package marble
import (
"encoding/base64"
"fmt"
"math"
"strconv"
"code.vikunja.io/api/pkg/user"
)
// Provider generates a random avatar based on https://github.com/boringdesigners/boring-avatars
type Provider struct {
}
// FlushCache is a no-op for the marble provider
func (p *Provider) FlushCache(_ *user.User) error { return nil }
const avatarSize = 80
var defaultColors = []string{
"#A3A948",
"#EDB92E",
"#F85931",
"#CE1836",
"#009989",
}
type props struct {
Color string
TranslateX int
TranslateY int
Rotate int
Scale float64
}
func getUnit(number int, rang, index int) int {
value := number % rang
digit := math.Floor(math.Mod(float64(number)/math.Pow(10, float64(index)), 10))
if index > 0 && (math.Mod(digit, 2) == 0) {
return -value
}
return value
}
func getPropsForUser(u *user.User, palette []string) []*props {
ps := []*props{}
for i := range 3 {
f := float64(getUnit(int(u.ID)*(i+1), avatarSize/10, 0))
ps = append(ps, &props{
Color: palette[(int(u.ID)+i)%len(palette)],
TranslateX: getUnit(int(u.ID)*(i+1), avatarSize/10, 1),
TranslateY: getUnit(int(u.ID)*(i+1), avatarSize/10, 2),
Scale: 1.2 + f/10,
Rotate: getUnit(int(u.ID)*(i+1), 360, 1),
})
}
return ps
}
// GenerateSVG renders a marble-style SVG avatar for the given user using the provided palette.
func GenerateSVG(u *user.User, size int64, palette []string) (avatar []byte, mimeType string, err error) {
s := strconv.FormatInt(size, 10)
avatarSizeStr := strconv.Itoa(avatarSize)
avatarSizeHalf := strconv.Itoa(avatarSize / 2)
ps := getPropsForUser(u, palette)
return []byte(``), "image/svg+xml", nil
}
// GenerateDataURI returns a base64-encoded data URI for a marble-style SVG avatar using the provided palette.
func GenerateDataURI(u *user.User, size int64, palette []string) (string, error) {
avatarData, mimeType, err := GenerateSVG(u, size, palette)
if err != nil {
return "", err
}
base64Data := base64.StdEncoding.EncodeToString(avatarData)
dataURI := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data)
return dataURI, nil
}
func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType string, err error) {
return GenerateSVG(u, size, defaultColors)
}
// AsDataURI returns a data URI for the SVG avatar
func (p *Provider) AsDataURI(u *user.User, size int64) (string, error) {
return GenerateDataURI(u, size, defaultColors)
}