Browse Source

Add update notification to Help menu item. Remove update popup dialog message, and remove "checkVersion" from settings.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
beefa87ef6
11 changed files with 135 additions and 146 deletions
  1. +3
    -1
      include/app/MenuBar.hpp
  2. +7
    -3
      include/app/common.hpp
  3. +0
    -1
      include/settings.hpp
  4. +82
    -79
      src/app/MenuBar.cpp
  5. +1
    -36
      src/app/Scene.cpp
  6. +32
    -3
      src/app/common.cpp
  7. +3
    -2
      src/main.cpp
  8. +2
    -2
      src/patch.cpp
  9. +4
    -8
      src/plugin.cpp
  10. +0
    -7
      src/settings.cpp
  11. +1
    -4
      src/window.cpp

+ 3
- 1
include/app/MenuBar.hpp View File

@@ -8,10 +8,12 @@ namespace app {


struct MenuBar : widget::OpaqueWidget {
MenuBar();
void draw(const DrawArgs &args) override;
};


MenuBar *createMenuBar();


} // namespace app
} // namespace rack

+ 7
- 3
include/app/common.hpp View File

@@ -12,9 +12,10 @@ namespace rack {
namespace app {


extern const char APP_NAME[];
extern const char APP_VERSION[];
extern const char API_URL[];
extern std::string APP_NAME;
extern std::string APP_VERSION;
extern std::string APP_NEW_VERSION;
extern std::string API_URL;

static const float SVG_DPI = 75.0;
static const float MM_PER_IN = 25.4;
@@ -47,5 +48,8 @@ static const math::Vec RACK_OFFSET = RACK_GRID_SIZE.mult(math::Vec(2000, 100));
static const math::Vec BUS_BOARD_GRID_SIZE = math::Vec(RACK_GRID_WIDTH * 20, RACK_GRID_HEIGHT);


void init();


} // namespace app
} // namespace rack

+ 0
- 1
include/settings.hpp View File

@@ -34,7 +34,6 @@ extern int threadCount;
extern bool paramTooltip;
extern bool cpuMeter;
extern bool lockModules;
extern bool checkVersion;
extern float frameRateLimit;
extern bool frameRateSync;
extern bool skipLoadOnLaunch;


+ 82
- 79
src/app/MenuBar.cpp View File

@@ -34,6 +34,29 @@ struct MenuButton : ui::Button {
if (APP->event->draggedWidget == this)
state = BND_ACTIVE;
bndMenuItem(args.vg, 0.0, 0.0, box.size.x, box.size.y, state, -1, text.c_str());
Widget::draw(args);
}
};

struct NotificationIcon : widget::Widget {
void draw(const DrawArgs &args) override {
nvgBeginPath(args.vg);
float radius = 4;
nvgCircle(args.vg, radius, radius, radius);
nvgFillColor(args.vg, nvgRGBf(1.0, 0.0, 0.0));
nvgFill(args.vg);
nvgStrokeColor(args.vg, nvgRGBf(0.5, 0.0, 0.0));
nvgStroke(args.vg);
}
};

struct UrlItem : ui::MenuItem {
std::string url;
void onAction(const event::Action &e) override {
std::thread t([=]() {
system::openBrowser(url);
});
t.detach();
}
};

@@ -421,15 +444,6 @@ struct EngineButton : MenuButton {

static bool isLoggingIn = false;

struct RegisterItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t([]() {
system::openBrowser("https://vcvrack.com/");
});
t.detach();
}
};

struct AccountEmailField : ui::TextField {
ui::TextField *passwordField;
void onSelectKey(const event::SelectKey &e) override {
@@ -478,15 +492,6 @@ struct LogInItem : ui::MenuItem {
}
};

struct ManageItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t([]() {
system::openBrowser("https://vcvrack.com/plugins.html");
});
t.detach();
}
};

struct SyncItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t([=]() {
@@ -496,16 +501,6 @@ struct SyncItem : ui::MenuItem {
}
};

struct UpdateItem : ui::MenuItem {
std::string changelogUrl;
void onAction(const event::Action &e) override {
std::thread t([=]() {
system::openBrowser(changelogUrl);
});
t.detach();
}
};

#if 0
struct SyncButton : ui::Button {
bool checked = false;
@@ -589,8 +584,9 @@ struct PluginsMenu : ui::Menu {
}

if (plugin::isLoggedIn()) {
ManageItem *manageItem = new ManageItem;
UrlItem *manageItem = new UrlItem;
manageItem->text = "Manage";
manageItem->url = "https://vcvrack.com/plugins.html";
addChild(manageItem);

LogOutItem *logOutItem = new LogOutItem;
@@ -610,22 +606,23 @@ struct PluginsMenu : ui::Menu {
addChild(updatesLabel);

for (const plugin::Update &update : plugin::updates) {
UpdateItem *updateItem = new UpdateItem;
UrlItem *updateItem = new UrlItem;
updateItem->text = update.pluginSlug;
plugin::Plugin *p = plugin::getPlugin(update.pluginSlug);
if (p) {
updateItem->rightText += "v" + p->version + " → ";
}
updateItem->rightText += "v" + update.version;
updateItem->changelogUrl = update.changelogUrl;
updateItem->url = update.changelogUrl;
updateItem->disabled = update.changelogUrl.empty();
addChild(updateItem);
}
}
}
else {
RegisterItem *registerItem = new RegisterItem;
UrlItem *registerItem = new UrlItem;
registerItem->text = "Register VCV account";
registerItem->url = "https://vcvrack.com/";
addChild(registerItem);

AccountEmailField *emailField = new AccountEmailField;
@@ -649,24 +646,23 @@ struct PluginsMenu : ui::Menu {
};

struct PluginsButton : MenuButton {
NotificationIcon *notification;

PluginsButton() {
notification = new NotificationIcon;
addChild(notification);
}

void onAction(const event::Action &e) override {
ui::Menu *menu = createMenu<PluginsMenu>();
menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y));
menu->box.size.x = box.size.x;
}

void draw(const DrawArgs &args) override {
MenuButton::draw(args);

if (0) {
// Notification circle
nvgBeginPath(args.vg);
nvgCircle(args.vg, 4, 2, 4.0);
nvgFillColor(args.vg, nvgRGBf(1.0, 0.0, 0.0));
nvgFill(args.vg);
nvgStrokeColor(args.vg, nvgRGBf(0.5, 0.0, 0.0));
nvgStroke(args.vg);
}
void step() override {
notification->box.pos = math::Vec(0, 0);
notification->visible = false;
MenuButton::step();
}
};

@@ -674,26 +670,6 @@ struct PluginsButton : MenuButton {
// Help
////////////////////

struct ManualItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t(system::openBrowser, "https://vcvrack.com/manual/");
t.detach();
}
};

struct WebsiteItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t(system::openBrowser, "https://vcvrack.com/");
t.detach();
}
};

struct CheckVersionItem : ui::MenuItem {
void onAction(const event::Action &e) override {
settings::checkVersion ^= true;
}
};

struct UserFolderItem : ui::MenuItem {
void onAction(const event::Action &e) override {
std::thread t(system::openFolder, asset::user(""));
@@ -702,43 +678,75 @@ struct UserFolderItem : ui::MenuItem {
};

struct HelpButton : MenuButton {
NotificationIcon *notification;

HelpButton() {
notification = new NotificationIcon;
addChild(notification);
}

void onAction(const event::Action &e) override {
ui::Menu *menu = createMenu();
menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y));
menu->box.size.x = box.size.x;

ManualItem *manualItem = new ManualItem;
UrlItem *manualItem = new UrlItem;
manualItem->text = "Manual";
manualItem->rightText = "F1";
manualItem->url = "https://vcvrack.com/manual/";
menu->addChild(manualItem);

WebsiteItem *websiteItem = new WebsiteItem;
UrlItem *websiteItem = new UrlItem;
websiteItem->text = "VCVRack.com";
websiteItem->url = "https://vcvrack.com/";
menu->addChild(websiteItem);

CheckVersionItem *checkVersionItem = new CheckVersionItem;
checkVersionItem->text = "Check version on launch";
checkVersionItem->rightText = CHECKMARK(settings::checkVersion);
menu->addChild(checkVersionItem);
if (hasUpdate()) {
UrlItem *updateItem = new UrlItem;
updateItem->text = "Update " + APP_NAME;
updateItem->rightText = APP_VERSION + " → " + APP_NEW_VERSION;
updateItem->url = "https://vcvrack.com/";
menu->addChild(updateItem);
}

UserFolderItem *folderItem = new UserFolderItem;
folderItem->text = "Open user folder";
menu->addChild(folderItem);
}

void step() override {
notification->box.pos = math::Vec(0, 0);
notification->visible = hasUpdate();
MenuButton::step();
}

bool hasUpdate() {
return !APP_NEW_VERSION.empty() && APP_NEW_VERSION != APP_VERSION;
}
};

////////////////////
// MenuBar
////////////////////

MenuBar::MenuBar() {
void MenuBar::draw(const DrawArgs &args) {
bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL);
bndBevel(args.vg, 0.0, 0.0, box.size.x, box.size.y);

Widget::draw(args);
}


MenuBar *createMenuBar() {
MenuBar *menuBar = new MenuBar;

const float margin = 5;
box.size.y = BND_WIDGET_HEIGHT + 2*margin;
menuBar->box.size.y = BND_WIDGET_HEIGHT + 2*margin;

ui::SequentialLayout *layout = new ui::SequentialLayout;
layout->box.pos = math::Vec(margin, margin);
layout->spacing = math::Vec(0, 0);
addChild(layout);
menuBar->addChild(layout);

FileButton *fileButton = new FileButton;
fileButton->text = "File";
@@ -763,13 +771,8 @@ MenuBar::MenuBar() {
HelpButton *helpButton = new HelpButton;
helpButton->text = "Help";
layout->addChild(helpButton);
}

void MenuBar::draw(const DrawArgs &args) {
bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL);
bndBevel(args.vg, 0.0, 0.0, box.size.x, box.size.y);

Widget::draw(args);
return menuBar;
}




+ 1
- 36
src/app/Scene.cpp View File

@@ -21,7 +21,7 @@ Scene::Scene() {

rack = rackScroll->rackWidget;

menuBar = new MenuBar;
menuBar = createMenuBar();
addChild(menuBar);
rackScroll->box.pos.y = menuBar->box.size.y;

@@ -46,24 +46,6 @@ void Scene::step() {
settings::save(asset::user("settings.json"));
}

// Request latest version from server
if (!settings::devMode && checkVersion && !checkedVersion) {
std::thread t(&Scene::runCheckVersion, this);
t.detach();
checkedVersion = true;
}

// Version popup message
if (!latestVersion.empty()) {
std::string versionMessage = string::f("Rack v%s is available.\n\nYou have Rack v%s.\n\nClose Rack and download new version on the website?", latestVersion.c_str(), app::APP_VERSION);
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) {
std::thread t(system::openBrowser, "https://vcvrack.com/");
t.detach();
APP->window->close();
}
latestVersion = "";
}

Widget::step();
}

@@ -166,23 +148,6 @@ void Scene::onPathDrop(const event::PathDrop &e) {
}
}

void Scene::runCheckVersion() {
std::string versionUrl = app::API_URL;
versionUrl += "/version";
json_t *versionResJ = network::requestJson(network::METHOD_GET, versionUrl, NULL);

if (versionResJ) {
json_t *versionJ = json_object_get(versionResJ, "version");
if (versionJ) {
std::string version = json_string_value(versionJ);
if (version != app::APP_VERSION) {
latestVersion = version;
}
}
json_decref(versionResJ);
}
}


} // namespace app
} // namespace rack

+ 32
- 3
src/app/common.cpp View File

@@ -1,14 +1,43 @@
#include "app/common.hpp"
#include "settings.hpp"
#include "network.hpp"
#include <thread>


namespace rack {
namespace app {


const char APP_NAME[] = "VCV Rack";
const char APP_VERSION[] = TOSTRING(VERSION);
const char API_URL[] = "https://api.vcvrack.com";
std::string APP_NAME = "VCV Rack";
std::string APP_VERSION = TOSTRING(VERSION);
std::string APP_NEW_VERSION;
std::string API_URL = "https://api.vcvrack.com";

static void checkVersion() {
std::string versionUrl = app::API_URL + "/version2";
json_t *versionResJ = network::requestJson(network::METHOD_GET, versionUrl, NULL);
if (!versionResJ) {
WARN("Request for version failed");
return;
}
DEFER({
json_decref(versionResJ);
});

json_t *versionJ = json_object_get(versionResJ, "version");
if (versionJ)
APP_NEW_VERSION = json_string_value(versionJ);
}

void init() {
// TODO
if (!settings::devMode || 1) {
std::thread t([] {
checkVersion();
});
t.detach();
}
}


} // namespace app


+ 3
- 2
src/main.cpp View File

@@ -48,7 +48,7 @@ int main(int argc, char *argv[]) {
#if defined ARCH_WIN
// Windows global mutex to prevent multiple instances
// Handle will be closed by Windows when the process ends
HANDLE instanceMutex = CreateMutexA(NULL, true, app::APP_NAME);
HANDLE instanceMutex = CreateMutexA(NULL, true, app::APP_NAME.c_str());
if (GetLastError() == ERROR_ALREADY_EXISTS) {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Rack is already running. Multiple Rack instances are not supported.");
exit(1);
@@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
#endif

// Log environment
INFO("%s v%s", app::APP_NAME, app::APP_VERSION);
INFO("%s v%s", app::APP_NAME.c_str(), app::APP_VERSION.c_str());
INFO("%s", system::getOperatingSystemInfo().c_str());
if (settings::devMode)
INFO("Development mode");
@@ -139,6 +139,7 @@ int main(int argc, char *argv[]) {
keyboard::init();
gamepad::init();
plugin::init();
app::init();
if (!settings::headless) {
ui::init();
windowInit();


+ 2
- 2
src/patch.cpp View File

@@ -230,7 +230,7 @@ json_t *PatchManager::toJson() {
json_t *rootJ = json_object();

// version
json_t *versionJ = json_string(app::APP_VERSION);
json_t *versionJ = json_string(app::APP_VERSION.c_str());
json_object_set_new(rootJ, "version", versionJ);

// Merge with RackWidget JSON
@@ -251,7 +251,7 @@ void PatchManager::fromJson(json_t *rootJ) {
if (versionJ)
version = json_string_value(versionJ);
if (version != app::APP_VERSION) {
INFO("Patch was made with Rack v%s, current Rack version is v%s", version.c_str(), app::APP_VERSION);
INFO("Patch was made with Rack v%s, current Rack version is v%s", version.c_str(), app::APP_VERSION.c_str());
}

// Detect old patches with ModuleWidget::params/inputs/outputs indices.


+ 4
- 8
src/plugin.cpp View File

@@ -166,8 +166,7 @@ static bool syncUpdate(const Update &update) {
std::string arch = "lin";
#endif

std::string downloadUrl = app::API_URL;
downloadUrl += "/download";
std::string downloadUrl = app::API_URL + "/download";
downloadUrl += "?token=" + network::encodeUrl(settings::token);
downloadUrl += "&slug=" + network::encodeUrl(update.pluginSlug);
downloadUrl += "&version=" + network::encodeUrl(update.version);
@@ -350,8 +349,7 @@ void logIn(const std::string &email, const std::string &password) {
json_t *reqJ = json_object();
json_object_set(reqJ, "email", json_string(email.c_str()));
json_object_set(reqJ, "password", json_string(password.c_str()));
std::string url = app::API_URL;
url += "/token";
std::string url = app::API_URL + "/token";
json_t *resJ = network::requestJson(network::METHOD_POST, url, reqJ);
json_decref(reqJ);

@@ -391,8 +389,7 @@ void queryUpdates() {
// Get user's plugins list
json_t *pluginsReqJ = json_object();
json_object_set(pluginsReqJ, "token", json_string(settings::token.c_str()));
std::string pluginsUrl = app::API_URL;
pluginsUrl += "/plugins";
std::string pluginsUrl = app::API_URL + "/plugins";
json_t *pluginsResJ = network::requestJson(network::METHOD_GET, pluginsUrl, pluginsReqJ);
json_decref(pluginsReqJ);
if (!pluginsResJ) {
@@ -410,8 +407,7 @@ void queryUpdates() {
}

// Get community manifests
std::string manifestsUrl = app::API_URL;
manifestsUrl += "/community/manifests";
std::string manifestsUrl = app::API_URL + "/community/manifests";
json_t *manifestsResJ = network::requestJson(network::METHOD_GET, manifestsUrl, NULL);
if (!manifestsResJ) {
WARN("Request for community manifests failed");


+ 0
- 7
src/settings.cpp View File

@@ -29,7 +29,6 @@ int threadCount = 1;
bool paramTooltip = false;
bool cpuMeter = false;
bool lockModules = false;
bool checkVersion = true;
float frameRateLimit = 70.0;
bool frameRateSync = true;
bool skipLoadOnLaunch = false;
@@ -76,8 +75,6 @@ json_t *toJson() {

json_object_set_new(rootJ, "lockModules", json_boolean(lockModules));

json_object_set_new(rootJ, "checkVersion", json_boolean(checkVersion));

json_object_set_new(rootJ, "frameRateLimit", json_real(frameRateLimit));

json_object_set_new(rootJ, "frameRateSync", json_boolean(frameRateSync));
@@ -174,10 +171,6 @@ void fromJson(json_t *rootJ) {
if (lockModulesJ)
lockModules = json_boolean_value(lockModulesJ);

json_t *checkVersionJ = json_object_get(rootJ, "checkVersion");
if (checkVersionJ)
checkVersion = json_boolean_value(checkVersionJ);

json_t *frameRateLimitJ = json_object_get(rootJ, "frameRateLimit");
if (frameRateLimitJ)
frameRateLimit = json_number_value(frameRateLimitJ);


+ 1
- 4
src/window.cpp View File

@@ -327,10 +327,7 @@ void Window::run() {
gamepad::step();

// Set window title
std::string windowTitle;
windowTitle = app::APP_NAME;
windowTitle += " v";
windowTitle += app::APP_VERSION;
std::string windowTitle = app::APP_NAME + " v" + app::APP_VERSION;
if (!APP->patch->path.empty()) {
windowTitle += " - ";
if (!APP->history->isSaved())


Loading…
Cancel
Save