diff --git a/include/plugin.hpp b/include/plugin.hpp index e727bc44..a2073ba7 100644 --- a/include/plugin.hpp +++ b/include/plugin.hpp @@ -14,12 +14,18 @@ namespace rack { namespace plugin { +struct Update { + std::string pluginSlug; + std::string version; +}; + + void init(); void destroy(); void logIn(const std::string &email, const std::string &password); void logOut(); -void query(); -void sync(); +void queryUpdates(); +void syncUpdates(); void cancelDownload(); bool isLoggedIn(); Plugin *getPlugin(const std::string &pluginSlug); @@ -33,6 +39,7 @@ extern const std::set allowedTags; extern std::vector plugins; extern std::string loginStatus; +extern std::vector updates; extern float downloadProgress; extern std::string downloadName; diff --git a/src/app/MenuBar.cpp b/src/app/MenuBar.cpp index d1205242..0059ad4a 100644 --- a/src/app/MenuBar.cpp +++ b/src/app/MenuBar.cpp @@ -562,24 +562,38 @@ struct PluginsMenu : ui::Menu { void refresh() { clearChildren(); - if (0) { - ui::ProgressBar *downloadProgressBar = new ui::ProgressBar; - downloadProgressBar->quantity = new DownloadQuantity; - addChild(downloadProgressBar); - } - else if (plugin::isLoggedIn()) { + if (plugin::isLoggedIn()) { ManageItem *manageItem = new ManageItem; manageItem->text = "Manage"; addChild(manageItem); + LogOutItem *logOutItem = new LogOutItem; + logOutItem->text = "Log out"; + addChild(logOutItem); + SyncItem *syncItem = new SyncItem; syncItem->text = "Update all"; - syncItem->disabled = true; addChild(syncItem); - LogOutItem *logOutItem = new LogOutItem; - logOutItem->text = "Log out"; - addChild(logOutItem); + if (!plugin::updates.empty()) { + addChild(new ui::MenuEntry); + + ui::MenuLabel *updatesLabel = new ui::MenuLabel; + updatesLabel->text = "Updates"; + addChild(updatesLabel); + + for (plugin::Update &update : plugin::updates) { + ui::MenuItem *updateItem = new ui::MenuItem; + updateItem->disabled = true; + updateItem->text = update.pluginSlug; + plugin::Plugin *p = plugin::getPlugin(update.pluginSlug); + if (p) { + updateItem->rightText += "v" + p->version + " → "; + } + updateItem->rightText += "v" + update.version; + addChild(updateItem); + } + } } else { RegisterItem *registerItem = new RegisterItem; diff --git a/src/plugin.cpp b/src/plugin.cpp index fcabc720..d7b9743b 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -369,6 +369,13 @@ void init() { extractZip(fundamentalSrc.c_str(), pluginsDir.c_str()); loadPlugin(fundamentalDir); } + + // TEMP + // Sync in a detached thread + std::thread t([]{ + queryUpdates(); + }); + t.detach(); } void destroy() { @@ -427,9 +434,10 @@ void logOut() { settings::token = ""; } -void query() { +void queryUpdates() { if (settings::token.empty()) return; + updates.clear(); // Get user's plugins list json_t *pluginsReqJ = json_object(); @@ -464,8 +472,45 @@ void query() { json_decref(manifestsResJ); }); - json_dumpf(pluginsResJ, stderr, JSON_INDENT(2)); - json_dumpf(manifestsResJ, stderr, JSON_INDENT(2)); + json_t *manifestsJ = json_object_get(manifestsResJ, "manifests"); + json_t *pluginsJ = json_object_get(pluginsResJ, "plugins"); + + size_t pluginIndex; + json_t *pluginJ; + json_array_foreach(pluginsJ, pluginIndex, pluginJ) { + Update update; + // Get plugin manifest + update.pluginSlug = json_string_value(pluginJ); + json_t *manifestJ = json_object_get(manifestsJ, update.pluginSlug.c_str()); + if (!manifestJ) { + WARN("VCV account has plugin %s but no manifest was found", update.pluginSlug.c_str()); + continue; + } + + // Get version + // TODO Change this to "version" when API changes + json_t *versionJ = json_object_get(manifestJ, "latestVersion"); + if (!versionJ) { + WARN("Plugin %s has no version in manifest", update.pluginSlug.c_str()); + continue; + } + update.version = json_string_value(versionJ); + + // Check status + json_t *statusJ = json_object_get(manifestJ, "status"); + if (!statusJ) + continue; + std::string status = json_string_value(statusJ); + if (status != "available") + continue; + + // Check if update is needed + Plugin *p = getPlugin(update.pluginSlug); + if (p && p->version == update.version) + continue; + + updates.push_back(update); + } } void sync() { @@ -473,8 +518,6 @@ void sync() { if (settings::token.empty()) return false; - bool available = false; - if (!dryRun) { downloadProgress = 0.0; downloadName = "Updating plugins..."; @@ -654,6 +697,7 @@ bool isSlugValid(const std::string &slug) { std::vector plugins; std::string loginStatus; +std::vector updates; float downloadProgress = 0.f; std::string downloadName;