瀏覽代碼

:art: 集市支持已安装的包单独显示 https://github.com/siyuan-note/siyuan/issues/5678

Liang Ding 2 年之前
父節點
當前提交
6072f8a3a1
共有 7 個文件被更改,包括 159 次插入101 次删除
  1. 9 0
      kernel/api/bazaar.go
  2. 1 0
      kernel/api/router.go
  3. 60 22
      kernel/bazaar/icon.go
  4. 78 7
      kernel/bazaar/package.go
  5. 5 22
      kernel/bazaar/template.go
  6. 5 28
      kernel/bazaar/theme.go
  7. 1 22
      kernel/bazaar/widget.go

+ 9 - 0
kernel/api/bazaar.go

@@ -107,6 +107,15 @@ func getBazaarIcon(c *gin.Context) {
 	}
 	}
 }
 }
 
 
+func getInstalledIcon(c *gin.Context) {
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	ret.Data = map[string]interface{}{
+		"packages": bazaar.InstalledIcons(),
+	}
+}
+
 func installBazaarIcon(c *gin.Context) {
 func installBazaarIcon(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)
 	defer c.JSON(http.StatusOK, ret)

+ 1 - 0
kernel/api/router.go

@@ -237,6 +237,7 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/bazaar/installBazaarWidget", model.CheckAuth, installBazaarWidget)
 	ginServer.Handle("POST", "/api/bazaar/installBazaarWidget", model.CheckAuth, installBazaarWidget)
 	ginServer.Handle("POST", "/api/bazaar/uninstallBazaarWidget", model.CheckAuth, uninstallBazaarWidget)
 	ginServer.Handle("POST", "/api/bazaar/uninstallBazaarWidget", model.CheckAuth, uninstallBazaarWidget)
 	ginServer.Handle("POST", "/api/bazaar/getBazaarIcon", model.CheckAuth, getBazaarIcon)
 	ginServer.Handle("POST", "/api/bazaar/getBazaarIcon", model.CheckAuth, getBazaarIcon)
+	ginServer.Handle("POST", "/api/bazaar/getInstalledIcon", model.CheckAuth, getInstalledIcon)
 	ginServer.Handle("POST", "/api/bazaar/installBazaarIcon", model.CheckAuth, installBazaarIcon)
 	ginServer.Handle("POST", "/api/bazaar/installBazaarIcon", model.CheckAuth, installBazaarIcon)
 	ginServer.Handle("POST", "/api/bazaar/uninstallBazaarIcon", model.CheckAuth, uninstallBazaarIcon)
 	ginServer.Handle("POST", "/api/bazaar/uninstallBazaarIcon", model.CheckAuth, uninstallBazaarIcon)
 	ginServer.Handle("POST", "/api/bazaar/getBazaarTemplate", model.CheckAuth, getBazaarTemplate)
 	ginServer.Handle("POST", "/api/bazaar/getBazaarTemplate", model.CheckAuth, getBazaarTemplate)

+ 60 - 22
kernel/bazaar/icon.go

@@ -19,10 +19,12 @@ package bazaar
 import (
 import (
 	"errors"
 	"errors"
 	"os"
 	"os"
+	"path/filepath"
 	"sort"
 	"sort"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 
 
+	"github.com/88250/gulu"
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	ants "github.com/panjf2000/ants/v2"
 	ants "github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
@@ -31,28 +33,7 @@ import (
 )
 )
 
 
 type Icon struct {
 type Icon struct {
-	Author  string `json:"author"`
-	URL     string `json:"url"`
-	Version string `json:"version"`
-
-	Name            string `json:"name"`
-	RepoURL         string `json:"repoURL"`
-	RepoHash        string `json:"repoHash"`
-	PreviewURL      string `json:"previewURL"`
-	PreviewURLThumb string `json:"previewURLThumb"`
-
-	README string `json:"readme"`
-
-	Installed  bool   `json:"installed"`
-	Outdated   bool   `json:"outdated"`
-	Current    bool   `json:"current"`
-	Updated    string `json:"updated"`
-	Stars      int    `json:"stars"`
-	OpenIssues int    `json:"openIssues"`
-	Size       int64  `json:"size"`
-	HSize      string `json:"hSize"`
-	HUpdated   string `json:"hUpdated"`
-	Downloads  int    `json:"downloads"`
+	Package
 }
 }
 
 
 func Icons() (icons []*Icon) {
 func Icons() (icons []*Icon) {
@@ -114,6 +95,63 @@ func Icons() (icons []*Icon) {
 	return
 	return
 }
 }
 
 
+func InstalledIcons() (ret []*Icon) {
+	dir, err := os.Open(filepath.Join(util.DataDir, "icons"))
+	if nil != err {
+		logging.LogWarnf("open icons folder [%s] failed: %s", util.ThemesPath, err)
+		return
+	}
+	iconDirs, err := dir.Readdir(-1)
+	if nil != err {
+		logging.LogWarnf("read icons folder failed: %s", err)
+		return
+	}
+	dir.Close()
+
+	bazaarIcons := Icons()
+
+	for _, iconDir := range iconDirs {
+		if !iconDir.IsDir() {
+			continue
+		}
+		dirName := iconDir.Name()
+		if isBuiltInIcon(dirName) {
+			continue
+		}
+
+		iconConf, parseErr := IconJSON(dirName)
+		if nil != parseErr || nil == iconConf {
+			continue
+		}
+
+		icon := &Icon{}
+		icon.Name = iconConf["name"].(string)
+		icon.Author = iconConf["author"].(string)
+		icon.URL = iconConf["url"].(string)
+		icon.Version = iconConf["version"].(string)
+		icon.RepoURL = icon.URL
+		icon.PreviewURL = "/appearance/icons/" + dirName + "/preview.png"
+		icon.PreviewURLThumb = "/appearance/icons/" + dirName + "/preview.png"
+		icon.Updated = iconDir.ModTime().Format("2006-01-02 15:04:05")
+		icon.Size = iconDir.Size()
+		icon.HSize = humanize.Bytes(uint64(icon.Size))
+		icon.HUpdated = formatUpdated(icon.Updated)
+		readme, readErr := os.ReadFile(filepath.Join(util.DataDir, "icons", dirName, "README.md"))
+		if nil != readErr {
+			logging.LogWarnf("read install icon README.md failed: %s", readErr)
+			continue
+		}
+		icon.README = gulu.Str.FromBytes(readme)
+		icon.Outdated = isOutdatedIcon(icon.URL, icon.Version, bazaarIcons)
+		ret = append(ret, icon)
+	}
+	return
+}
+
+func isBuiltInIcon(dirName string) bool {
+	return "and" == dirName || "material" == dirName
+}
+
 func InstallIcon(repoURL, repoHash, installPath string, systemID string) error {
 func InstallIcon(repoURL, repoHash, installPath string, systemID string) error {
 	repoURLHash := repoURL + "@" + repoHash
 	repoURLHash := repoURL + "@" + repoHash
 	data, err := downloadPackage(repoURLHash, true, systemID)
 	data, err := downloadPackage(repoURLHash, true, systemID)

+ 78 - 7
kernel/bazaar/package.go

@@ -37,6 +37,53 @@ import (
 	"golang.org/x/text/transform"
 	"golang.org/x/text/transform"
 )
 )
 
 
+type Package struct {
+	Author  string `json:"author"`
+	URL     string `json:"url"`
+	Version string `json:"version"`
+
+	Name            string `json:"name"`
+	RepoURL         string `json:"repoURL"`
+	RepoHash        string `json:"repoHash"`
+	PreviewURL      string `json:"previewURL"`
+	PreviewURLThumb string `json:"previewURLThumb"`
+
+	README string `json:"readme"`
+
+	Installed  bool   `json:"installed"`
+	Outdated   bool   `json:"outdated"`
+	Current    bool   `json:"current"`
+	Updated    string `json:"updated"`
+	Stars      int    `json:"stars"`
+	OpenIssues int    `json:"openIssues"`
+	Size       int64  `json:"size"`
+	HSize      string `json:"hSize"`
+	HUpdated   string `json:"hUpdated"`
+	Downloads  int    `json:"downloads"`
+}
+
+func IconJSON(iconDirName string) (ret map[string]interface{}, err error) {
+	p := filepath.Join(util.ThemesPath, iconDirName, "icon.json")
+	if !gulu.File.IsExist(p) {
+		err = os.ErrNotExist
+		return
+	}
+	data, err := os.ReadFile(p)
+	if nil != err {
+		logging.LogErrorf("read icon.json [%s] failed: %s", p, err)
+		return
+	}
+	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
+		logging.LogErrorf("parse icon.json [%s] failed: %s", p, err)
+		return
+	}
+	if 4 > len(ret) {
+		logging.LogWarnf("invalid icon.json [%s]", p)
+		return nil, errors.New("invalid icon.json")
+	}
+	return
+}
+
 func TemplateJSON(templateDirName string) (ret map[string]interface{}, err error) {
 func TemplateJSON(templateDirName string) (ret map[string]interface{}, err error) {
 	p := filepath.Join(util.ThemesPath, templateDirName, "template.json")
 	p := filepath.Join(util.ThemesPath, templateDirName, "template.json")
 	if !gulu.File.IsExist(p) {
 	if !gulu.File.IsExist(p) {
@@ -103,18 +150,42 @@ func getPkgIndex(pkgType string) (ret map[string]interface{}, err error) {
 	return
 	return
 }
 }
 
 
-func isOutdatedPkg(fullURL, version string, pkgIndex map[string]interface{}) bool {
+func isOutdatedTheme(fullURL, version string, bazaarThemes []*Theme) bool {
+	if !strings.HasPrefix(fullURL, "https://github.com/") {
+		return false
+	}
+
+	url := strings.TrimPrefix(fullURL, "https://github.com/")
+	for _, pkg := range bazaarThemes {
+		if url == pkg.URL && version != pkg.Version {
+			return true
+		}
+	}
+	return false
+}
+
+func isOutdatedIcon(fullURL, version string, bazaarIcons []*Icon) bool {
+	if !strings.HasPrefix(fullURL, "https://github.com/") {
+		return false
+	}
+
+	url := strings.TrimPrefix(fullURL, "https://github.com/")
+	for _, pkg := range bazaarIcons {
+		if url == pkg.URL && version != pkg.Version {
+			return true
+		}
+	}
+	return false
+}
+
+func isOutdatedTemplate(fullURL, version string, bazaarTemplates []*Template) bool {
 	if !strings.HasPrefix(fullURL, "https://github.com/") {
 	if !strings.HasPrefix(fullURL, "https://github.com/") {
 		return false
 		return false
 	}
 	}
 
 
 	url := strings.TrimPrefix(fullURL, "https://github.com/")
 	url := strings.TrimPrefix(fullURL, "https://github.com/")
-	repos := pkgIndex["repos"].([]interface{})
-	for _, repo := range repos {
-		r := repo.(map[string]interface{})
-		repoURL := r["url"].(string)
-		repoVer := r["version"].(string)
-		if url == repoURL && version != repoVer {
+	for _, pkg := range bazaarTemplates {
+		if url == pkg.URL && version != pkg.Version {
 			return true
 			return true
 		}
 		}
 	}
 	}

+ 5 - 22
kernel/bazaar/template.go

@@ -34,27 +34,7 @@ import (
 )
 )
 
 
 type Template struct {
 type Template struct {
-	Author  string `json:"author"`
-	URL     string `json:"url"`
-	Version string `json:"version"`
-
-	Name            string `json:"name"`
-	RepoURL         string `json:"repoURL"`
-	RepoHash        string `json:"repoHash"`
-	PreviewURL      string `json:"previewURL"`
-	PreviewURLThumb string `json:"previewURLThumb"`
-
-	README string `json:"readme"`
-
-	Installed  bool   `json:"installed"`
-	Outdated   bool   `json:"outdated"`
-	Updated    string `json:"updated"`
-	Stars      int    `json:"stars"`
-	OpenIssues int    `json:"openIssues"`
-	Size       int64  `json:"size"`
-	HSize      string `json:"hSize"`
-	HUpdated   string `json:"hUpdated"`
-	Downloads  int    `json:"downloads"`
+	Package
 }
 }
 
 
 func Templates() (templates []*Template) {
 func Templates() (templates []*Template) {
@@ -131,11 +111,14 @@ func InstalledTemplates() (ret []*Template) {
 	}
 	}
 	dir.Close()
 	dir.Close()
 
 
+	bazaarTemplates := Templates()
+
 	for _, templateDir := range templateDirs {
 	for _, templateDir := range templateDirs {
 		if !templateDir.IsDir() {
 		if !templateDir.IsDir() {
 			continue
 			continue
 		}
 		}
 		dirName := templateDir.Name()
 		dirName := templateDir.Name()
+
 		templateConf, parseErr := TemplateJSON(dirName)
 		templateConf, parseErr := TemplateJSON(dirName)
 		if nil != parseErr || nil == templateConf {
 		if nil != parseErr || nil == templateConf {
 			continue
 			continue
@@ -159,7 +142,7 @@ func InstalledTemplates() (ret []*Template) {
 			continue
 			continue
 		}
 		}
 		template.README = gulu.Str.FromBytes(readme)
 		template.README = gulu.Str.FromBytes(readme)
-
+		template.Outdated = isOutdatedTemplate(template.URL, template.Version, bazaarTemplates)
 		ret = append(ret, template)
 		ret = append(ret, template)
 	}
 	}
 	return
 	return

+ 5 - 28
kernel/bazaar/theme.go

@@ -33,29 +33,9 @@ import (
 )
 )
 
 
 type Theme struct {
 type Theme struct {
-	Author  string   `json:"author"`
-	URL     string   `json:"url"`
-	Version string   `json:"version"`
-	Modes   []string `json:"modes"`
-
-	Name            string `json:"name"`
-	RepoURL         string `json:"repoURL"`
-	RepoHash        string `json:"repoHash"`
-	PreviewURL      string `json:"previewURL"`
-	PreviewURLThumb string `json:"previewURLThumb"`
-
-	README string `json:"readme"`
-
-	Installed  bool   `json:"installed"`
-	Outdated   bool   `json:"outdated"`
-	Current    bool   `json:"current"`
-	Updated    string `json:"updated"`
-	Stars      int    `json:"stars"`
-	OpenIssues int    `json:"openIssues"`
-	Size       int64  `json:"size"`
-	HSize      string `json:"hSize"`
-	HUpdated   string `json:"hUpdated"`
-	Downloads  int    `json:"downloads"`
+	Package
+
+	Modes []string `json:"modes"`
 }
 }
 
 
 func Themes() (ret []*Theme) {
 func Themes() (ret []*Theme) {
@@ -130,10 +110,7 @@ func InstalledThemes() (ret []*Theme) {
 	}
 	}
 	dir.Close()
 	dir.Close()
 
 
-	pkgIndex, err := getPkgIndex("themes")
-	if nil != err {
-		return
-	}
+	bazaarThemes := Themes()
 
 
 	for _, themeDir := range themeDirs {
 	for _, themeDir := range themeDirs {
 		if !themeDir.IsDir() {
 		if !themeDir.IsDir() {
@@ -168,7 +145,7 @@ func InstalledThemes() (ret []*Theme) {
 			continue
 			continue
 		}
 		}
 		theme.README = gulu.Str.FromBytes(readme)
 		theme.README = gulu.Str.FromBytes(readme)
-		theme.Outdated = isOutdatedPkg(theme.URL, theme.Version, pkgIndex)
+		theme.Outdated = isOutdatedTheme(theme.URL, theme.Version, bazaarThemes)
 		ret = append(ret, theme)
 		ret = append(ret, theme)
 	}
 	}
 	return
 	return

+ 1 - 22
kernel/bazaar/widget.go

@@ -31,28 +31,7 @@ import (
 )
 )
 
 
 type Widget struct {
 type Widget struct {
-	Author  string `json:"author"`
-	URL     string `json:"url"`
-	Version string `json:"version"`
-
-	Name            string `json:"name"`
-	RepoURL         string `json:"repoURL"`
-	RepoHash        string `json:"repoHash"`
-	PreviewURL      string `json:"previewURL"`
-	PreviewURLThumb string `json:"previewURLThumb"`
-
-	README string `json:"readme"`
-
-	Installed  bool   `json:"installed"`
-	Outdated   bool   `json:"outdated"`
-	Current    bool   `json:"current"`
-	Updated    string `json:"updated"`
-	Stars      int    `json:"stars"`
-	OpenIssues int    `json:"openIssues"`
-	Size       int64  `json:"size"`
-	HSize      string `json:"hSize"`
-	HUpdated   string `json:"hUpdated"`
-	Downloads  int    `json:"downloads"`
+	Package
 }
 }
 
 
 func Widgets() (widgets []*Widget) {
 func Widgets() (widgets []*Widget) {