diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 1c9dd7675..700b6adfd 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1440,6 +1440,10 @@ "231": "Deleting unreferenced data objects in cloud storage...", "232": "The cloud data storage has been purged. [%d] snapshots and [%d] data objects have been deleted, and a total of [%s] disk space has been released", "233": "Closing user guide...", - "234": "[%d/%d] Updated [%d] of readable paths of doc [%s]" + "234": "[%d/%d] Updated [%d] of readable paths of doc [%s]", + "235": "[%d/%d] is updating the marketplace package...", + "236": "[%d/%d] is updating the marketplace package [%s]...", + "237": "[%d] marketplace packages have all been updated successfully", + "238": "Marketplace package [%s] update failed, please try again later" } } diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 23f6c89ae..939aeecce 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1440,6 +1440,10 @@ "231": "Eliminar objetos de datos no referenciados en el almacenamiento en la nube...", "232": "Se ha eliminado el almacenamiento de datos en la nube. Se han eliminado [%d] instantáneas y [%d] objetos de datos, y se ha liberado un total de [%s] espacio en disco", "233": "Cerrando la guía del usuario...", - "234": "[%d/%d] Actualizado [%d] de rutas legibles del documento [%s]" + "234": "[%d/%d] Actualizado [%d] de rutas legibles del documento [%s]", + "235": "[%d/%d] está actualizando el paquete del mercado...", + "236": "[%d/%d] está actualizando el paquete del mercado [%s]...", + "237": "[%d] todos los paquetes del mercado se han actualizado correctamente", + "238": "Error en la actualización del paquete Marketplace [%s], inténtalo de nuevo más tarde" } } diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index a63e956b0..472757fe0 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1440,6 +1440,10 @@ "231": "Suppression des objets de données non référencés dans le stockage cloud...", "232": "Le stockage de données cloud a été purgé. [%d] instantanés et [%d] objets de données ont été supprimés, et un total de [%s] espace disque a été libéré", "233": "Fermeture du guide de l'utilisateur...", - "234": "[%d/%d] Mise à jour de [%d] des chemins lisibles du document [%s]" + "234": "[%d/%d] Mise à jour de [%d] des chemins lisibles du document [%s]", + "235": "[%d/%d] met à jour le package Marketplace...", + "236": "[%d/%d] met à jour le package Marketplace [%s]...", + "237": "[%d] packages Marketplace ont tous été mis à jour avec succès", + "238": "La mise à jour du package Marketplace [%s] a échoué, veuillez réessayer plus tard" } } diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index 6eebbae4f..b6b79c421 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1440,6 +1440,10 @@ "231": "正在刪除雲端儲存未引用資料物件...", "232": "雲端資料儲存清理完畢,已刪除 [%d] 個快照和 [%d] 個資料對象,共釋放 [%s] 磁碟空間", "233": "正在關閉用戶指南...", - "234": "[%d/%d] 已經更新 [%d] 個文件的可讀路徑 [%s]" + "234": "[%d/%d] 已經更新 [%d] 個文件的可讀路徑 [%s]", + "235": "[%d/%d] 正在更新市集包...", + "236": "[%d/%d] 正在更新市集包 [%s]...", + "237": "[%d] 個市集包已經全部更新成功", + "238": "市集包 [%s] 更新失敗,請稍後再試" } } diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 80775476c..12213464d 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1440,6 +1440,10 @@ "231": "正在删除云端存储未引用数据对象...", "232": "云端数据存储清理完毕,已删除 [%d] 个快照和 [%d] 个数据对象,共释放 [%s] 磁盘空间", "233": "正在关闭用户指南...", - "234": "[%d/%d] 已经更新 [%d] 个文档的可读路径 [%s]" + "234": "[%d/%d] 已经更新 [%d] 个文档的可读路径 [%s]", + "235": "[%d/%d] 正在更新集市包...", + "236": "[%d/%d] 正在更新集市包 [%s]...", + "237": "[%d] 个集市包已经全部更新成功", + "238": "集市包 [%s] 更新失败,请稍后再试" } } diff --git a/kernel/api/bazaar.go b/kernel/api/bazaar.go index d8fbcc73f..eeaf0fc5f 100644 --- a/kernel/api/bazaar.go +++ b/kernel/api/bazaar.go @@ -25,6 +25,19 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func batchUpdatePackage(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + arg, ok := util.JsonArg(c, ret) + if !ok { + return + } + + frontend := arg["frontend"].(string) + model.BatchUpdateBazaarPackages(frontend) +} + func getUpdatedPackage(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 d4bc60b9b..88d40ab05 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -330,7 +330,6 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/graph/getGraph", model.CheckAuth, getGraph) ginServer.Handle("POST", "/api/graph/getLocalGraph", model.CheckAuth, getLocalGraph) - ginServer.Handle("POST", "/api/bazaar/getUpdatedPackage", model.CheckAuth, getUpdatedPackage) ginServer.Handle("POST", "/api/bazaar/getBazaarPlugin", model.CheckAuth, getBazaarPlugin) ginServer.Handle("POST", "/api/bazaar/getInstalledPlugin", model.CheckAuth, getInstalledPlugin) ginServer.Handle("POST", "/api/bazaar/installBazaarPlugin", model.CheckAuth, model.CheckReadonly, installBazaarPlugin) @@ -352,6 +351,8 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/bazaar/installBazaarTheme", model.CheckAuth, model.CheckReadonly, installBazaarTheme) ginServer.Handle("POST", "/api/bazaar/uninstallBazaarTheme", model.CheckAuth, model.CheckReadonly, uninstallBazaarTheme) ginServer.Handle("POST", "/api/bazaar/getBazaarPackageREAME", model.CheckAuth, getBazaarPackageREAME) + ginServer.Handle("POST", "/api/bazaar/getUpdatedPackage", model.CheckAuth, getUpdatedPackage) + ginServer.Handle("POST", "/api/bazaar/batchUpdatePackage", model.CheckAuth, batchUpdatePackage) ginServer.Handle("POST", "/api/repo/initRepoKey", model.CheckAuth, model.CheckReadonly, initRepoKey) ginServer.Handle("POST", "/api/repo/initRepoKeyFromPassphrase", model.CheckAuth, model.CheckReadonly, initRepoKeyFromPassphrase) diff --git a/kernel/bazaar/package.go b/kernel/bazaar/package.go index 5720e31c5..6d0d106ac 100644 --- a/kernel/bazaar/package.go +++ b/kernel/bazaar/package.go @@ -530,9 +530,25 @@ func renderREADME(repoURL string, mdData []byte) (ret string, err error) { return } +var ( + packageLocks = map[string]*sync.Mutex{} + packageLocksLock = sync.Mutex{} +) + func downloadPackage(repoURLHash string, pushProgress bool, systemID string) (data []byte, err error) { + packageLocksLock.Lock() + defer packageLocksLock.Unlock() + // repoURLHash: https://github.com/88250/Comfortably-Numb@6286912c381ef3f83e455d06ba4d369c498238dc - pushID := repoURLHash[:strings.LastIndex(repoURLHash, "@")] + repoURL := repoURLHash[:strings.LastIndex(repoURLHash, "@")] + lock, ok := packageLocks[repoURLHash] + if !ok { + lock = &sync.Mutex{} + packageLocks[repoURLHash] = lock + } + lock.Lock() + defer lock.Unlock() + repoURLHash = strings.TrimPrefix(repoURLHash, "https://github.com/") u := util.BazaarOSSServer + "/package/" + repoURLHash buf := &bytes.Buffer{} @@ -540,7 +556,7 @@ func downloadPackage(repoURLHash string, pushProgress bool, systemID string) (da if pushProgress { progress := float32(info.DownloadedSize) / float32(info.Response.ContentLength) //logging.LogDebugf("downloading bazaar package [%f]", progress) - util.PushDownloadProgress(pushID, progress) + util.PushDownloadProgress(repoURL, progress) } }).Get(u) if nil != err { diff --git a/kernel/model/bazzar.go b/kernel/model/bazzar.go index ffe71755b..432369ca2 100644 --- a/kernel/model/bazzar.go +++ b/kernel/model/bazzar.go @@ -19,17 +19,100 @@ package model import ( "errors" "fmt" + "github.com/88250/gulu" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/util" "path" "path/filepath" "strings" "sync" - - "github.com/88250/gulu" - "github.com/siyuan-note/siyuan/kernel/util" + "time" "github.com/siyuan-note/siyuan/kernel/bazaar" ) +func BatchUpdateBazaarPackages(frontend string) { + plugins, widgets, icons, themes, templates := UpdatedPackages(frontend) + + total := len(plugins) + len(widgets) + len(icons) + len(themes) + len(templates) + if 1 > total { + return + } + + util.PushEndlessProgress(fmt.Sprintf(Conf.language(235), 1, total)) + defer util.PushClearProgress() + count := 1 + for _, plugin := range plugins { + err := bazaar.InstallPlugin(plugin.RepoURL, plugin.RepoHash, filepath.Join(util.DataDir, "plugins", plugin.Name), Conf.System.ID) + if nil != err { + logging.LogErrorf("update plugin [%s] failed: %s", plugin.Name, err) + util.PushErrMsg(fmt.Sprintf(Conf.language(238)), 5000) + return + } + + count++ + util.PushEndlessProgress(fmt.Sprintf(Conf.language(236), count, total, plugin.Name)) + } + + for _, widget := range widgets { + err := bazaar.InstallWidget(widget.RepoURL, widget.RepoHash, filepath.Join(util.DataDir, "widgets", widget.Name), Conf.System.ID) + if nil != err { + logging.LogErrorf("update widget [%s] failed: %s", widget.Name, err) + util.PushErrMsg(fmt.Sprintf(Conf.language(238)), 5000) + return + } + + count++ + util.PushEndlessProgress(fmt.Sprintf(Conf.language(236), count, total, widget.Name)) + } + + for _, icon := range icons { + err := bazaar.InstallIcon(icon.RepoURL, icon.RepoHash, filepath.Join(util.IconsPath, icon.Name), Conf.System.ID) + if nil != err { + logging.LogErrorf("update icon [%s] failed: %s", icon.Name, err) + util.PushErrMsg(fmt.Sprintf(Conf.language(238)), 5000) + return + } + + count++ + util.PushEndlessProgress(fmt.Sprintf(Conf.language(236), count, total, icon.Name)) + } + + for _, template := range templates { + err := bazaar.InstallTemplate(template.RepoURL, template.RepoHash, filepath.Join(util.DataDir, "templates", template.Name), Conf.System.ID) + if nil != err { + logging.LogErrorf("update template [%s] failed: %s", template.Name, err) + util.PushErrMsg(fmt.Sprintf(Conf.language(238)), 5000) + return + } + + count++ + util.PushEndlessProgress(fmt.Sprintf(Conf.language(236), count, total, template.Name)) + } + + for _, theme := range themes { + err := bazaar.InstallTheme(theme.RepoURL, theme.RepoHash, filepath.Join(util.ThemesPath, theme.Name), Conf.System.ID) + if nil != err { + logging.LogErrorf("update theme [%s] failed: %s", theme.Name, err) + util.PushErrMsg(fmt.Sprintf(Conf.language(238)), 5000) + return + } + + count++ + util.PushEndlessProgress(fmt.Sprintf(Conf.language(236), count, total, theme.Name)) + } + + util.ReloadUI() + + go func() { + util.WaitForUILoaded() + time.Sleep(500) + util.PushMsg(fmt.Sprintf(Conf.language(237), total), 5000) + }() + + return +} + func UpdatedPackages(frontend string) (plugins []*bazaar.Plugin, widgets []*bazaar.Widget, icons []*bazaar.Icon, themes []*bazaar.Theme, templates []*bazaar.Template) { wg := &sync.WaitGroup{} wg.Add(5)