yao/sui/storages/local/template.go
2023-12-07 23:14:39 +08:00

244 lines
5 KiB
Go

package local
import (
"fmt"
"io"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/google/uuid"
"github.com/yaoapp/yao/sui/core"
"golang.org/x/text/language"
)
// Assets get the assets treelist
func (tmpl *Template) Assets() []string {
return nil
}
// GetRoot get the root path
func (tmpl *Template) GetRoot() string {
return tmpl.Root
}
// Locales get the global locales
func (tmpl *Template) Locales() []core.SelectOption {
supportLocales := []core.SelectOption{}
path := filepath.Join(tmpl.Root, "__locales")
if !tmpl.local.fs.IsDir(path) {
return nil
}
dirs, err := tmpl.local.fs.ReadDir(path, false)
if err != nil {
return nil
}
for _, dir := range dirs {
locale := filepath.Base(dir)
label := language.Make(locale).String()
supportLocales = append(supportLocales, core.SelectOption{
Value: locale,
Label: label,
})
}
return supportLocales
}
// Themes get the global themes
func (tmpl *Template) Themes() []core.SelectOption {
return tmpl.Template.Themes
}
// MediaSearch search the asset
func (tmpl *Template) MediaSearch(query url.Values, page int, pageSize int) (core.MediaSearchResult, error) {
res := core.MediaSearchResult{Data: []core.Media{}, Page: page, PageSize: pageSize}
keyword := query.Get("keyword")
types := query["types"]
if types == nil {
types = []string{"image", "video", "audio"}
}
exts := tmpl.mediaExts(types)
path := filepath.Join(tmpl.Root, "__assets", "upload")
files, total, pagecnt, err := tmpl.local.fs.List(path, exts, page, pageSize, func(s string) bool {
if keyword == "" {
return true
}
return strings.Contains(s, keyword)
})
if err != nil {
return res, err
}
for _, file := range files {
file = strings.TrimPrefix(file, filepath.Join(tmpl.Root, "__assets", "upload"))
res.Data = append(res.Data, core.Media{
ID: file,
URL: filepath.Join("@assets", "upload", file),
Thumb: filepath.Join("@assets", "upload", file),
Type: tmpl.mediaType(file),
Width: 100,
Height: 100,
})
}
res.Next = page + 1
if (page+1)*pageSize >= total {
res.Next = 0
}
res.Prev = page - 1
if page == 1 {
res.Prev = 0
}
res.Total = total
res.PageCount = pagecnt
return res, nil
}
func (tmpl *Template) mediaExts(types []string) []string {
exts := []string{}
for _, typ := range types {
switch typ {
case "image":
exts = append(exts, []string{".jpg", ".jpeg", ".png"}...)
break
case "video":
exts = append(exts, []string{".mp4"}...)
break
case "audio":
exts = append(exts, []string{".mp3"}...)
break
}
}
return exts
}
func (tmpl *Template) mediaType(file string) string {
ext := strings.ToLower(filepath.Ext(file))
switch ext {
case ".jpg":
return "image"
case ".jpeg":
return "image"
case ".png":
return "image"
case ".gif":
return "image"
case ".bmp":
return "image"
case ".mp4":
return "video"
case ".mp3":
return "audio"
}
return "file"
}
// AssetUpload upload the asset
func (tmpl *Template) AssetUpload(reader io.Reader, name string) (string, error) {
fingerprint := strings.ToUpper(uuid.NewString())
dir := strings.Join([]string{string(os.PathSeparator), time.Now().Format("20060102")}, "")
ext := filepath.Ext(name)
file := filepath.Join(tmpl.Root, "__assets", "upload", dir, fmt.Sprintf("%s%s", fingerprint, ext))
_, err := tmpl.local.fs.Write(file, reader, 0644)
if err != nil {
return "", err
}
return filepath.Join("upload", dir, fmt.Sprintf("%s%s", fingerprint, ext)), nil
}
// Asset get the asset
func (tmpl *Template) Asset(file string, width, height uint) (*core.Asset, error) {
file = filepath.Join(tmpl.Root, "__assets", file)
if exist, _ := tmpl.local.fs.Exists(file); exist {
if width > 0 || height > 0 {
return tmpl.assetThumb(file, width, height)
}
content, err := tmpl.local.fs.ReadFile(file)
if err != nil {
return nil, err
}
typ := "text/plain"
switch filepath.Ext(file) {
case ".css":
typ = "text/css; charset=utf-8"
break
case ".js":
typ = "application/javascript; charset=utf-8"
break
case ".ts":
typ = "application/javascript; charset=utf-8"
break
case ".json":
typ = "application/json; charset=utf-8"
break
case ".html":
typ = "text/html; charset=utf-8"
break
default:
typ, err = tmpl.local.fs.MimeType(file)
if err != nil {
return nil, err
}
}
return &core.Asset{Type: typ, Content: content}, nil
}
return nil, fmt.Errorf("Asset %s not found", file)
}
func (tmpl *Template) assetThumb(file string, width, height uint) (*core.Asset, error) {
cacheFile := filepath.Join(tmpl.Root, "__assets", ".cache", fmt.Sprintf("%dx%d", width, height), file)
exist, _ := tmpl.local.fs.Exists(cacheFile)
if !exist {
err := tmpl.local.fs.Resize(file, cacheFile, width, height)
if err != nil {
return nil, err
}
}
typ, err := tmpl.local.fs.MimeType(file)
if err != nil {
return nil, err
}
content, err := tmpl.local.fs.ReadFile(cacheFile)
if err != nil {
return nil, err
}
return &core.Asset{Type: typ, Content: content}, nil
}