diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index c96fc15f5c..76e2afd308 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -47,6 +47,7 @@ Item { property bool showConfirmation: false; property bool hasPermissionToRezThis; property bool permissionExplanationCardVisible; + property bool isInstalled: false; property string originalStatusText; property string originalStatusColor; @@ -62,6 +63,12 @@ Item { showConfirmation = true; } } + + onAppInstalled: { + if (appHref === root.itemHref) { + root.isInstalled = true; + } + } } Connections { @@ -81,6 +88,10 @@ Item { } else { root.hasPermissionToRezThis = true; } + + if (itemType === "app") { + root.isInstalled = Commerce.isAppInstalled(root.itemHref); + } } onPurchaseStatusChangedChanged: { @@ -472,6 +483,40 @@ Item { } } + Rectangle { + id: appButtonContainer; + color: hifi.colors.white; + z: 994; + visible: root.isInstalled; + anchors.fill: buttonContainer; + + HifiControlsUit.Button { + id: openAppButton; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.light; + anchors.top: parent.top; + anchors.right: parent.right; + height: 44; + text: "OPEN" + onClicked: { + Commerce.openApp(root.itemHref); + } + } + + HifiControlsUit.Button { + id: uninstallAppButton; + color: hifi.buttons.noneBorderless; + colorScheme: hifi.colorSchemes.light; + anchors.bottom: parent.bottom; + anchors.right: parent.right; + height: 44; + text: "UNINSTALL" + onClicked: { + Commerce.uninstallApp(root.itemHref); + } + } + } + Button { id: buttonContainer; property int color: hifi.buttons.blue; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 0b583e6153..f9bb0d2003 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include "scripting/HMDScriptingInterface.h" QmlCommerce::QmlCommerce() { auto ledger = DependencyManager::get(); @@ -42,6 +44,8 @@ QmlCommerce::QmlCommerce() { connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); }); + + _appsPath = PathUtils::getAppDataPath() + "Apps"; } void QmlCommerce::getWalletStatus() { @@ -186,22 +190,32 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) { ledger->alreadyOwned(marketplaceId); } -static QString APP_PATH = PathUtils::getAppDataPath() + "apps"; bool QmlCommerce::isAppInstalled(const QString& itemHref) { QUrl appHref(itemHref); - QFileInfo appFile(APP_PATH + "/" + appHref.fileName()); - if (appFile.exists() && appFile.isFile()) { - return true; - } else { + // First check if .app.json exists + QFileInfo appFile(_appsPath + "/" + appHref.fileName()); + if (!(appFile.exists() && appFile.isFile())) { return false; } + + // Then check to see if script is running + auto runningScripts = DependencyManager::get()->getRunningScripts(); + foreach(const QString& runningScript, runningScripts) { + QUrl runningScriptURL = QUrl(runningScript); + qCDebug(commerce) << "ZRF FIXME" << runningScriptURL; + if (runningScriptURL == appHref) { + return true; + } + } + + return false; } bool QmlCommerce::installApp(const QString& itemHref) { - if (!QDir(APP_PATH).exists()) { - if (!QDir().mkdir(APP_PATH)) { - qCDebug(commerce) << "Couldn't make APP_PATH directory."; + if (!QDir(_appsPath).exists()) { + if (!QDir().mkdir(_appsPath)) { + qCDebug(commerce) << "Couldn't make _appsPath directory."; return false; } } @@ -228,7 +242,7 @@ bool QmlCommerce::installApp(const QString& itemHref) { // Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface auto requestData = request->getData(); - QFile appFile(APP_PATH + "/" + appHref.fileName()); + QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::WriteOnly)) { qCDebug(commerce) << "Couldn't open local .app.json file for creation."; return false; @@ -250,7 +264,7 @@ bool QmlCommerce::installApp(const QString& itemHref) { return false; } - emit appInstalled(appHref.fileName()); + emit appInstalled(itemHref); return true; } @@ -258,7 +272,7 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { QUrl appHref(itemHref); // Read from the file to know what .js script to stop - QFile appFile(APP_PATH + "/" + appHref.fileName()); + QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::ReadOnly)) { qCDebug(commerce) << "Couldn't open local .app.json file for deletion."; return false; @@ -279,6 +293,35 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { return false; } - emit appUninstalled(appHref.fileName()); + emit appUninstalled(itemHref); + return true; +} + +bool QmlCommerce::openApp(const QString& itemHref) { + QUrl appHref(itemHref); + + // Read from the file to know what .html or .qml document to open + QFile appFile(_appsPath + "/" + appHref.fileName()); + if (!appFile.open(QIODevice::ReadOnly)) { + qCDebug(commerce) << "Couldn't open local .app.json file."; + return false; + } + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString homeUrl = appFileJsonObject["homeURL"].toString(); + + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + if (homeUrl.contains(".qml", Qt::CaseInsensitive)) { + tablet->loadQMLSource(homeUrl); + } else if (homeUrl.contains(".html", Qt::CaseInsensitive)) { + tablet->gotoWebScreen(homeUrl); + } else { + qCDebug(commerce) << "Attempted to open unknown type of homeURL!"; + return false; + } + + DependencyManager::get()->openTablet(); + return true; } diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 60e52a441b..e0c018878d 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -81,9 +81,13 @@ protected: Q_INVOKABLE void replaceContentSet(const QString& itemHref); - Q_INVOKABLE bool isAppInstalled(const QString& itemHref); - Q_INVOKABLE bool installApp(const QString& itemHref); - Q_INVOKABLE bool uninstallApp(const QString& itemHref); + Q_INVOKABLE bool isAppInstalled(const QString& appHref); + Q_INVOKABLE bool installApp(const QString& appHref); + Q_INVOKABLE bool uninstallApp(const QString& appHref); + Q_INVOKABLE bool openApp(const QString& appHref); + +private: + QString _appsPath; }; #endif // hifi_QmlCommerce_h