diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a0dc17fac2d7e..bb6bfc4d2c0c7 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -52,6 +52,9 @@ if (OS_IS_WIN) elseif(OS_IS_LIN) + # add ssl support on local linux machine + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L /usr/local/lib -lcrypto -lssl") + if (MUSE_APP_INSTALL_SUFFIX) set(MSCORE_OUTPUT_NAME "${EXECUTABLE_NAME}${MUSE_APP_INSTALL_SUFFIX}") endif(MUSE_APP_INSTALL_SUFFIX) diff --git a/src/framework/stubs/update/musesoundscheckupdateservicestub.cpp b/src/framework/stubs/update/musesoundscheckupdateservicestub.cpp index 057588f71c8c4..29918ff691698 100644 --- a/src/framework/stubs/update/musesoundscheckupdateservicestub.cpp +++ b/src/framework/stubs/update/musesoundscheckupdateservicestub.cpp @@ -43,7 +43,3 @@ Progress MuseSoundsCheckUpdateServiceStub::updateProgress() { return Progress(); } - -void MuseSoundsCheckUpdateServiceStub::openMuseHub() -{ -} diff --git a/src/framework/stubs/update/musesoundscheckupdateservicestub.h b/src/framework/stubs/update/musesoundscheckupdateservicestub.h index d305995bd9230..f3a6a091cacbd 100644 --- a/src/framework/stubs/update/musesoundscheckupdateservicestub.h +++ b/src/framework/stubs/update/musesoundscheckupdateservicestub.h @@ -34,8 +34,6 @@ class MuseSoundsCheckUpdateServiceStub : public IMuseSoundsCheckUpdateService RetVal lastCheckResult() override; Progress updateProgress() override; - - void openMuseHub() override; }; } diff --git a/src/framework/update/imusesoundscheckupdateservice.h b/src/framework/update/imusesoundscheckupdateservice.h index 7520371922da8..10b0449185589 100644 --- a/src/framework/update/imusesoundscheckupdateservice.h +++ b/src/framework/update/imusesoundscheckupdateservice.h @@ -23,7 +23,6 @@ #define MUSE_UPDATE_IMUSESOUNDSCHECKUPDATESERVICE_H #include "types/retval.h" -#include "io/path.h" #include "progress.h" #include "updatetypes.h" @@ -44,8 +43,6 @@ class IMuseSoundsCheckUpdateService : MODULE_EXPORT_INTERFACE virtual RetVal lastCheckResult() = 0; virtual Progress updateProgress() = 0; - - virtual void openMuseHub() = 0; }; } diff --git a/src/framework/update/internal/musesoundscheckupdatescenario.cpp b/src/framework/update/internal/musesoundscheckupdatescenario.cpp index 5fd7bc97bcaf0..6830fb898be1c 100644 --- a/src/framework/update/internal/musesoundscheckupdatescenario.cpp +++ b/src/framework/update/internal/musesoundscheckupdatescenario.cpp @@ -23,18 +23,23 @@ #include "musesoundscheckupdatescenario.h" #include "global/concurrency/concurrent.h" +#include "global/defer.h" +#include "global/containers.h" +#include "global/stringutils.h" +#include "global/types/val.h" +#include "global/types/translatablestring.h" #include "updateerrors.h" -#include "types/val.h" - -#include "defer.h" #include "log.h" using namespace muse; using namespace muse::update; using namespace muse::actions; +static const char* DEFAULT_IMAGE_URL = "qrc:/qml/Muse/Update/resources/muse_sounds_promo.png"; +static const TranslatableString DEFAULT_ACTION_TITLE("update", "Take me to Muse Hub"); + void MuseSoundsCheckUpdateScenario::delayedInit() { if (service()->needCheckForUpdate() && multiInstancesProvider()->instances().size() == 1) { @@ -141,6 +146,18 @@ void MuseSoundsCheckUpdateScenario::showReleaseInfo(const ReleaseInfo& info) query.addParam("notes", Val(info.notes)); query.addParam("features", Val(info.additionInfo.at("features"))); + if (info.actionTitle.empty()) { + query.addParam("actionTitle", Val(DEFAULT_ACTION_TITLE.qTranslated())); + } else { + query.addParam("actionTitle", Val(QString::fromStdString(info.actionTitle))); + } + + if (info.imageUrl.empty()) { + query.addParam("imageUrl", Val(QString(DEFAULT_IMAGE_URL))); + } else { + query.addParam("imageUrl", Val(QString::fromStdString(info.imageUrl))); + } + RetVal rv = interactive()->open(query); if (!rv.ret) { LOGD() << rv.ret.toString(); @@ -150,6 +167,26 @@ void MuseSoundsCheckUpdateScenario::showReleaseInfo(const ReleaseInfo& info) QString actionCode = rv.val.toQString(); if (actionCode == "openMuseHub") { - service()->openMuseHub(); + tryOpenMuseHub(info.actions); } } + +void MuseSoundsCheckUpdateScenario::tryOpenMuseHub(ValList actions) const +{ + if (actions.empty()) { + LOGE() << "not actions to open Muse Hub"; + return; + } + + std::string action = muse::takeFirst(actions).toString(); + LOGI() << "try open: " << action; + + if (muse::strings::startsWith(action, "http")) { // or https + interactive()->openUrl(action); + return; + } + + interactive()->openApp(muse::Uri(action)).onReject(this, [this, actions](int, const std::string&) { + tryOpenMuseHub(actions); + }); +} diff --git a/src/framework/update/internal/musesoundscheckupdatescenario.h b/src/framework/update/internal/musesoundscheckupdatescenario.h index 047f3047ef546..4635793221bfb 100644 --- a/src/framework/update/internal/musesoundscheckupdatescenario.h +++ b/src/framework/update/internal/musesoundscheckupdatescenario.h @@ -60,6 +60,7 @@ class MuseSoundsCheckUpdateScenario : public IMuseSoundsCheckUpdateScenario, pub void th_checkForUpdate(); void showReleaseInfo(const ReleaseInfo& info); + void tryOpenMuseHub(ValList actions) const; bool m_checkProgress = false; ProgressPtr m_checkProgressChannel = nullptr; diff --git a/src/framework/update/internal/musesoundscheckupdateservice.cpp b/src/framework/update/internal/musesoundscheckupdateservice.cpp index 1ee087fba8996..1088a2277c41e 100644 --- a/src/framework/update/internal/musesoundscheckupdateservice.cpp +++ b/src/framework/update/internal/musesoundscheckupdateservice.cpp @@ -22,6 +22,8 @@ #include "musesoundscheckupdateservice.h" +#include + #include #include #include @@ -29,13 +31,15 @@ #include #include +#include "global/types/version.h" + #include "../updateerrors.h" -#include "types/version.h" -#include "defer.h" #include "log.h" static const muse::Uri MUSEHUB_APP_URI("musehub://?from=musescore"); +static const muse::Uri MUSEHUB_APP_V1_URI("muse-hub://?from=musescore"); +static const std::string MUSEHUB_WEB_URL = "https://www.musehub.com/"; using namespace muse::update; using namespace muse::network; @@ -118,31 +122,6 @@ muse::Progress MuseSoundsCheckUpdateService::updateProgress() return m_updateProgress; } -void MuseSoundsCheckUpdateService::openMuseHub() -{ - auto openMuseHubWebsite = [this]() { - static const std::string MUSEHUB_URL = "https://www.musehub.com/"; - interactive()->openUrl(MUSEHUB_URL); - }; - -#ifdef Q_OS_WIN - interactive()->openApp(MUSEHUB_APP_URI).onReject(this, [=](int, const std::string&) { - static const muse::Uri MUSEHUB_APP_V1_URI("muse-hub://?from=musescore"); - interactive()->openApp(MUSEHUB_APP_V1_URI).onReject(this, [=](int, const std::string&) { - openMuseHubWebsite(); - }); - }); - return; -#elif defined(Q_OS_MAC) - interactive()->openApp(MUSEHUB_APP_URI).onReject(this, [=](int, const std::string&) { - openMuseHubWebsite(); - }); - return; -#else - openMuseHubWebsite(); -#endif -} - muse::RetVal MuseSoundsCheckUpdateService::parseRelease(const QByteArray& json) const { RetVal result; @@ -150,10 +129,33 @@ muse::RetVal MuseSoundsCheckUpdateService::parseRelease(const QByte QJsonParseError err; QJsonDocument jsonDoc = QJsonDocument::fromJson(json, &err); if (err.error != QJsonParseError::NoError || !jsonDoc.isObject()) { + LOGE() << "parse error: " << err.errorString(); result.ret = make_ret(Err::NoUpdate); return result; } + /* + { + "version": String, + "image_url": String, // it can be base64 data, like "data:image/png;base64,iVBORw0KGgoA......" + "content": { + "locale_code": { + "notes": String, + "features": [String] + "action_title": String // title of action button + } + }, + + // open app or web page url, try in order, + // like this ["musehub://?from=musescore", "muse-hub://?from=musescore", "https://www.musehub.com"] + "actions": { + "windows": [String], + "macos": [String], + "linux": [String] + } + } + */ + QJsonObject releaseObj = jsonDoc.object(); if (releaseObj.empty()) { @@ -182,17 +184,55 @@ muse::RetVal MuseSoundsCheckUpdateService::parseRelease(const QByte result.ret = make_ok(); result.val.version = releaseObj.value("version").toString().toStdString(); + result.val.imageUrl = releaseObj.value("image_url").toString().toStdString(); result.val.notes = contentLocaleObj.value("notes").toString().toStdString(); - ValList featuresList; QJsonArray features = contentLocaleObj.value("features").toArray(); for (const QJsonValue& feature : features) { featuresList.push_back(Val(feature.toString().toStdString())); } - result.val.additionInfo.insert({ "features", Val(featuresList) }); + result.val.actionTitle = contentLocaleObj.value("action_title").toString().toStdString(); + QJsonObject actionsObj = releaseObj.value("actions").toObject(); + +#ifdef Q_OS_WIN + QJsonArray actionsArr = actionsObj.value("windows").toArray(); + for (const QJsonValue& a : actionsArr) { + result.val.actions.push_back(Val(a.toString().toStdString())); + } + + // def + if (result.val.actions.empty()) { + result.val.actions.push_back(Val(MUSEHUB_APP_URI.toString())); + result.val.actions.push_back(Val(MUSEHUB_APP_V1_URI.toString())); + result.val.actions.push_back(Val(MUSEHUB_WEB_URL)); + } + +#elif defined(Q_OS_MAC) + QJsonArray actionsArr = actionsObj.value("macos").toArray(); + for (const QJsonValue& a : actionsArr) { + result.val.actions.push_back(Val(a.toString().toStdString())); + } + + // def + if (result.val.actions.empty()) { + result.val.actions.push_back(Val(MUSEHUB_APP_URI.toString())); + result.val.actions.push_back(Val(MUSEHUB_WEB_URL)); + } +#else + QJsonArray actionsArr = actionsObj.value("linux").toArray(); + for (const QJsonValue& a : actionsArr) { + result.val.actions.push_back(Val(a.toString().toStdString())); + } + + // def + if (result.val.actions.empty()) { + result.val.actions.push_back(Val(MUSEHUB_WEB_URL)); + } +#endif + return result; } diff --git a/src/framework/update/internal/musesoundscheckupdateservice.h b/src/framework/update/internal/musesoundscheckupdateservice.h index fc581a2f49cfb..d25a30b1ab0d2 100644 --- a/src/framework/update/internal/musesoundscheckupdateservice.h +++ b/src/framework/update/internal/musesoundscheckupdateservice.h @@ -54,8 +54,6 @@ class MuseSoundsCheckUpdateService : public IMuseSoundsCheckUpdateService, publi Progress updateProgress() override; - void openMuseHub() override; - private: RetVal parseRelease(const QByteArray& json) const; diff --git a/src/framework/update/qml/Muse/Update/MuseSoundsReleaseInfoDialog.qml b/src/framework/update/qml/Muse/Update/MuseSoundsReleaseInfoDialog.qml index 2932c341e415f..3eb0653c3bd99 100644 --- a/src/framework/update/qml/Muse/Update/MuseSoundsReleaseInfoDialog.qml +++ b/src/framework/update/qml/Muse/Update/MuseSoundsReleaseInfoDialog.qml @@ -33,6 +33,8 @@ StyledDialogView { property alias notes: view.notes property alias features: featuresViewRepeater.model + property alias imageUrl: image.source + property alias actionTitle: buttons.defaultButtonName contentWidth: 530 contentHeight: 510 @@ -77,8 +79,6 @@ StyledDialogView { Layout.fillWidth: true Layout.preferredHeight: 186 - - source: "qrc:/qml/Muse/Update/resources/muse_sounds_promo.png" } Item { diff --git a/src/framework/update/qml/Muse/Update/internal/MuseSoundsReleaseInfoBottomPanel.qml b/src/framework/update/qml/Muse/Update/internal/MuseSoundsReleaseInfoBottomPanel.qml index 50e45a9a138f9..34027cd816975 100644 --- a/src/framework/update/qml/Muse/Update/internal/MuseSoundsReleaseInfoBottomPanel.qml +++ b/src/framework/update/qml/Muse/Update/internal/MuseSoundsReleaseInfoBottomPanel.qml @@ -28,7 +28,7 @@ import Muse.UiComponents 1.0 RowLayout { id: root - property string defaultButtonName: openMuseHubButton.text + property alias defaultButtonName: openMuseHubButton.text property NavigationPanel navigationPanel: NavigationPanel { name: "UpdateBottomPanel" @@ -65,8 +65,6 @@ RowLayout { Layout.alignment: Qt.AlignVCenter Layout.preferredWidth: (root.width - root.spacing) / 2 - text: qsTrc("update", "Take me to Muse Hub") - accentButton: true navigation.name: "OpenMuseHubButton" diff --git a/src/framework/update/qml/Muse/Update/resources/muse_sounds_promo.png b/src/framework/update/qml/Muse/Update/resources/muse_sounds_promo.png index f95511ac70f5c..d5e716b2db27b 100644 Binary files a/src/framework/update/qml/Muse/Update/resources/muse_sounds_promo.png and b/src/framework/update/qml/Muse/Update/resources/muse_sounds_promo.png differ diff --git a/src/framework/update/updatetypes.h b/src/framework/update/updatetypes.h index 6b373880c6b9a..89dc007edf5e6 100644 --- a/src/framework/update/updatetypes.h +++ b/src/framework/update/updatetypes.h @@ -47,11 +47,15 @@ struct ReleaseInfo { std::string fileName; std::string fileUrl; + std::string imageUrl; // it can be base64 data, like "data:image/png;base64,iVBORw0KGgoA......" std::string notes; PrevReleasesNotesList previousReleasesNotes; ValMap additionInfo; + std::string actionTitle; // title of action button + ValList actions; // open app or web page url, try in order + bool isValid() const { return !version.empty(); @@ -92,7 +96,10 @@ static inline ValMap releaseInfoToValMap(const ReleaseInfo& info) { "fileUrl", Val(info.fileUrl) }, { "notes", Val(info.notes) }, { "previousReleasesNotes", Val(releasesNotesToValList(info.previousReleasesNotes)) }, - { "additionalInfo", Val(info.additionInfo) } + { "additionalInfo", Val(info.additionInfo) }, + { "imageUrl", Val(info.imageUrl) }, + { "actionTitle", Val(info.actionTitle) }, + { "actions", Val(info.actions) }, }; } @@ -105,6 +112,9 @@ static inline ReleaseInfo releaseInfoFromValMap(const ValMap& map) info.notes = map.at("notes").toString(); info.previousReleasesNotes = releasesNotesFromValList(map.at("previousReleasesNotes").toList()); info.additionInfo = map.at("additionalInfo").toMap(); + info.imageUrl = map.at("imageUrl").toString(); + info.actionTitle = map.at("actionTitle").toString(); + info.actions = map.at("actions").toList(); return info; }