@@ -14,12 +14,18 @@ namespace rack { | |||||
namespace plugin { | namespace plugin { | ||||
struct Update { | |||||
std::string pluginSlug; | |||||
std::string version; | |||||
}; | |||||
void init(); | void init(); | ||||
void destroy(); | void destroy(); | ||||
void logIn(const std::string &email, const std::string &password); | void logIn(const std::string &email, const std::string &password); | ||||
void logOut(); | void logOut(); | ||||
void query(); | |||||
void sync(); | |||||
void queryUpdates(); | |||||
void syncUpdates(); | |||||
void cancelDownload(); | void cancelDownload(); | ||||
bool isLoggedIn(); | bool isLoggedIn(); | ||||
Plugin *getPlugin(const std::string &pluginSlug); | Plugin *getPlugin(const std::string &pluginSlug); | ||||
@@ -33,6 +39,7 @@ extern const std::set<std::string> allowedTags; | |||||
extern std::vector<Plugin*> plugins; | extern std::vector<Plugin*> plugins; | ||||
extern std::string loginStatus; | extern std::string loginStatus; | ||||
extern std::vector<Update> updates; | |||||
extern float downloadProgress; | extern float downloadProgress; | ||||
extern std::string downloadName; | extern std::string downloadName; | ||||
@@ -562,24 +562,38 @@ struct PluginsMenu : ui::Menu { | |||||
void refresh() { | void refresh() { | ||||
clearChildren(); | 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 *manageItem = new ManageItem; | ||||
manageItem->text = "Manage"; | manageItem->text = "Manage"; | ||||
addChild(manageItem); | addChild(manageItem); | ||||
LogOutItem *logOutItem = new LogOutItem; | |||||
logOutItem->text = "Log out"; | |||||
addChild(logOutItem); | |||||
SyncItem *syncItem = new SyncItem; | SyncItem *syncItem = new SyncItem; | ||||
syncItem->text = "Update all"; | syncItem->text = "Update all"; | ||||
syncItem->disabled = true; | |||||
addChild(syncItem); | 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 { | else { | ||||
RegisterItem *registerItem = new RegisterItem; | RegisterItem *registerItem = new RegisterItem; | ||||
@@ -369,6 +369,13 @@ void init() { | |||||
extractZip(fundamentalSrc.c_str(), pluginsDir.c_str()); | extractZip(fundamentalSrc.c_str(), pluginsDir.c_str()); | ||||
loadPlugin(fundamentalDir); | loadPlugin(fundamentalDir); | ||||
} | } | ||||
// TEMP | |||||
// Sync in a detached thread | |||||
std::thread t([]{ | |||||
queryUpdates(); | |||||
}); | |||||
t.detach(); | |||||
} | } | ||||
void destroy() { | void destroy() { | ||||
@@ -427,9 +434,10 @@ void logOut() { | |||||
settings::token = ""; | settings::token = ""; | ||||
} | } | ||||
void query() { | |||||
void queryUpdates() { | |||||
if (settings::token.empty()) | if (settings::token.empty()) | ||||
return; | return; | ||||
updates.clear(); | |||||
// Get user's plugins list | // Get user's plugins list | ||||
json_t *pluginsReqJ = json_object(); | json_t *pluginsReqJ = json_object(); | ||||
@@ -464,8 +472,45 @@ void query() { | |||||
json_decref(manifestsResJ); | 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() { | void sync() { | ||||
@@ -473,8 +518,6 @@ void sync() { | |||||
if (settings::token.empty()) | if (settings::token.empty()) | ||||
return false; | return false; | ||||
bool available = false; | |||||
if (!dryRun) { | if (!dryRun) { | ||||
downloadProgress = 0.0; | downloadProgress = 0.0; | ||||
downloadName = "Updating plugins..."; | downloadName = "Updating plugins..."; | ||||
@@ -654,6 +697,7 @@ bool isSlugValid(const std::string &slug) { | |||||
std::vector<Plugin*> plugins; | std::vector<Plugin*> plugins; | ||||
std::string loginStatus; | std::string loginStatus; | ||||
std::vector<Update> updates; | |||||
float downloadProgress = 0.f; | float downloadProgress = 0.f; | ||||
std::string downloadName; | std::string downloadName; | ||||