diff --git a/kernel/api/bazaar.go b/kernel/api/bazaar.go index 22aa56d8b..7df942210 100644 --- a/kernel/api/bazaar.go +++ b/kernel/api/bazaar.go @@ -165,6 +165,15 @@ func getBazaarTemplate(c *gin.Context) { } } +func getInstalledTemplate(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + ret.Data = map[string]interface{}{ + "packages": bazaar.InstalledTemplates(), + } +} + func installBazaarTemplate(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret) diff --git a/kernel/api/router.go b/kernel/api/router.go index 6985dce66..58acba501 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -240,10 +240,11 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/bazaar/installBazaarIcon", model.CheckAuth, installBazaarIcon) ginServer.Handle("POST", "/api/bazaar/uninstallBazaarIcon", model.CheckAuth, uninstallBazaarIcon) ginServer.Handle("POST", "/api/bazaar/getBazaarTemplate", model.CheckAuth, getBazaarTemplate) + ginServer.Handle("POST", "/api/bazaar/getInstalledTemplate", model.CheckAuth, getInstalledTemplate) ginServer.Handle("POST", "/api/bazaar/installBazaarTemplate", model.CheckAuth, installBazaarTemplate) ginServer.Handle("POST", "/api/bazaar/uninstallBazaarTemplate", model.CheckAuth, uninstallBazaarTemplate) ginServer.Handle("POST", "/api/bazaar/getBazaarTheme", model.CheckAuth, getBazaarTheme) - ginServer.Handle("POST", "/api/bazaar/getInstallTheme", model.CheckAuth, getInstalledTheme) + ginServer.Handle("POST", "/api/bazaar/getInstalledTheme", model.CheckAuth, getInstalledTheme) ginServer.Handle("POST", "/api/bazaar/installBazaarTheme", model.CheckAuth, installBazaarTheme) ginServer.Handle("POST", "/api/bazaar/uninstallBazaarTheme", model.CheckAuth, uninstallBazaarTheme) ginServer.Handle("POST", "/api/bazaar/getBazaarPackageREAME", model.CheckAuth, getBazaarPackageREAME) diff --git a/kernel/bazaar/package.go b/kernel/bazaar/package.go index 12f8b7462..329b65370 100644 --- a/kernel/bazaar/package.go +++ b/kernel/bazaar/package.go @@ -37,6 +37,50 @@ import ( "golang.org/x/text/transform" ) +func TemplateJSON(templateDirName string) (ret map[string]interface{}, err error) { + p := filepath.Join(util.ThemesPath, templateDirName, "template.json") + if !gulu.File.IsExist(p) { + err = os.ErrNotExist + return + } + data, err := os.ReadFile(p) + if nil != err { + logging.LogErrorf("read template.json [%s] failed: %s", p, err) + return + } + if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err { + logging.LogErrorf("parse template.json [%s] failed: %s", p, err) + return + } + if 4 > len(ret) { + logging.LogWarnf("invalid template.json [%s]", p) + return nil, errors.New("invalid template.json") + } + return +} + +func ThemeJSON(themeDirName string) (ret map[string]interface{}, err error) { + p := filepath.Join(util.ThemesPath, themeDirName, "theme.json") + if !gulu.File.IsExist(p) { + err = os.ErrNotExist + return + } + data, err := os.ReadFile(p) + if nil != err { + logging.LogErrorf("read theme.json [%s] failed: %s", p, err) + return + } + if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err { + logging.LogErrorf("parse theme.json [%s] failed: %s", p, err) + return + } + if 5 > len(ret) { + logging.LogWarnf("invalid theme.json [%s]", p) + return nil, errors.New("invalid theme.json") + } + return +} + func GetPackageREADME(repoURL, repoHash string, systemID string) (ret string) { repoURLHash := repoURL + "@" + repoHash data, err := downloadPackage(repoURLHash+"/README.md", false, systemID) diff --git a/kernel/bazaar/template.go b/kernel/bazaar/template.go index c08083264..72c43e4de 100644 --- a/kernel/bazaar/template.go +++ b/kernel/bazaar/template.go @@ -19,11 +19,13 @@ package bazaar import ( "errors" "os" + "path/filepath" "sort" "strings" "sync" "time" + "github.com/88250/gulu" "github.com/dustin/go-humanize" "github.com/panjf2000/ants/v2" "github.com/siyuan-note/httpclient" @@ -130,6 +132,53 @@ func Templates() (templates []*Template) { return } +func InstalledTemplates() (ret []*Template) { + dir, err := os.Open(filepath.Join(util.DataDir, "templates")) + if nil != err { + logging.LogWarnf("open templates folder [%s] failed: %s", util.ThemesPath, err) + return + } + templateDirs, err := dir.Readdir(-1) + if nil != err { + logging.LogWarnf("read templates folder failed: %s", err) + return + } + dir.Close() + + for _, templateDir := range templateDirs { + if !templateDir.IsDir() { + continue + } + dirName := templateDir.Name() + templateConf, parseErr := TemplateJSON(dirName) + if nil != parseErr || nil == templateConf { + continue + } + + template := &Template{} + template.Name = templateConf["name"].(string) + template.Author = templateConf["author"].(string) + template.URL = templateConf["url"].(string) + template.Version = templateConf["version"].(string) + template.RepoURL = template.URL + template.PreviewURL = "/templates/" + dirName + "/preview.png" + template.PreviewURLThumb = "/templates/" + dirName + "/preview.png" + template.Updated = templateDir.ModTime().Format("2006-01-02 15:04:05") + template.Size = templateDir.Size() + template.HSize = humanize.Bytes(uint64(template.Size)) + template.HUpdated = formatUpdated(template.Updated) + readme, readErr := os.ReadFile(filepath.Join(util.DataDir, "templates", dirName, "README.md")) + if nil != readErr { + logging.LogWarnf("read install template README.md failed: %s", readErr) + continue + } + template.README = gulu.Str.FromBytes(readme) + + ret = append(ret, template) + } + return +} + func InstallTemplate(repoURL, repoHash, installPath string, systemID string) error { repoURLHash := repoURL + "@" + repoHash data, err := downloadPackage(repoURLHash, true, systemID) diff --git a/kernel/bazaar/theme.go b/kernel/bazaar/theme.go index 77ccaec94..2bb5257a4 100644 --- a/kernel/bazaar/theme.go +++ b/kernel/bazaar/theme.go @@ -178,9 +178,7 @@ func InstalledThemes() (ret []*Theme) { } theme.README = gulu.Str.FromBytes(readme) - if !existThemes(ret, theme) { - ret = append(ret, theme) - } + ret = append(ret, theme) } return } @@ -189,15 +187,6 @@ func isBuiltInTheme(dirName string) bool { return "daylight" == dirName || "midnight" == dirName } -func existThemes(themes []*Theme, theme *Theme) bool { - for _, t := range themes { - if t.Name == theme.Name { - return true - } - } - return false -} - func InstallTheme(repoURL, repoHash, installPath string, systemID string) error { repoURLHash := repoURL + "@" + repoHash data, err := downloadPackage(repoURLHash, true, systemID) @@ -215,25 +204,3 @@ func UninstallTheme(installPath string) error { //logging.Logger.Infof("uninstalled theme [%s]", installPath) return nil } - -func ThemeJSON(themeName string) (ret map[string]interface{}, err error) { - p := filepath.Join(util.ThemesPath, themeName, "theme.json") - if !gulu.File.IsExist(p) { - err = os.ErrNotExist - return - } - data, err := os.ReadFile(p) - if nil != err { - logging.LogErrorf("read theme.json [%s] failed: %s", p, err) - return - } - if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err { - logging.LogErrorf("parse theme.json [%s] failed: %s", p, err) - return - } - if 5 > len(ret) { - logging.LogWarnf("invalid theme.json [%s]", p) - return nil, errors.New("invalid theme.json") - } - return -} diff --git a/kernel/server/serve.go b/kernel/server/serve.go index be4ab1711..b56b22983 100644 --- a/kernel/server/serve.go +++ b/kernel/server/serve.go @@ -97,6 +97,10 @@ func serveEmojis(ginServer *gin.Engine) { ginServer.Static("/emojis/", filepath.Join(util.DataDir, "emojis")) } +func serveTemplates(ginServer *gin.Engine) { + ginServer.Static("/templates/", filepath.Join(util.DataDir, "templates")) +} + func serveAppearance(ginServer *gin.Engine) { siyuan := ginServer.Group("", model.CheckAuth)