lots of fun initial progress!

This commit is contained in:
Zach Fox 2018-02-22 13:56:46 -08:00
parent 3d4e6de6ab
commit 4d2d7fa51f
6 changed files with 120 additions and 8 deletions

View file

@ -146,7 +146,8 @@ Rectangle {
}
onItemTypeChanged: {
if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "avatar") {
if (root.itemType === "entity" || root.itemType === "wearable" ||
root.itemType === "contentSet" || root.itemType === "avatar" || root.itemType === "app") {
root.isCertified = true;
} else {
root.isCertified = false;
@ -679,7 +680,7 @@ Rectangle {
id: rezNowButton;
enabled: (root.itemType === "entity" && root.canRezCertifiedItems) ||
(root.itemType === "contentSet" && Entities.canReplaceContent()) ||
root.itemType === "wearable" || root.itemType === "avatar";
root.itemType === "wearable" || root.itemType === "avatar" || root.itemType === "app";
buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
color: hifi.buttons.red;
colorScheme: hifi.colorSchemes.light;
@ -712,6 +713,9 @@ Rectangle {
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;";
lightboxPopup.visible = true;
} else if (root.itemType === "app") {
// "Run" button is separate.
Commerce.installApp(root.itemHref);
} else {
sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
rezzedNotifContainer.visible = true;

View file

@ -506,6 +506,9 @@ Item {
sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref});
} else if (root.itemType === "avatar") {
sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
} else if (root.itemType === "app") {
// "Run" and "Uninstall" buttons are separate.
Commerce.installApp(root.itemHref);
} else {
sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
root.showConfirmation = true;

View file

@ -10,6 +10,7 @@
//
#include "QmlCommerce.h"
#include "CommerceLogging.h"
#include "Application.h"
#include "DependencyManager.h"
#include "Ledger.h"
@ -17,6 +18,7 @@
#include <AccountManager.h>
#include <Application.h>
#include <UserActivityLogger.h>
#include <ScriptEngines.h>
QmlCommerce::QmlCommerce() {
auto ledger = DependencyManager::get<Ledger>();
@ -183,3 +185,100 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) {
auto ledger = DependencyManager::get<Ledger>();
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 {
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.";
return false;
}
}
QUrl appHref(itemHref);
auto request =
std::unique_ptr<ResourceRequest>(DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref));
if (!request) {
qCDebug(commerce) << "Couldn't create resource request for app.";
return false;
}
QEventLoop loop;
connect(request.get(), &ResourceRequest::finished, &loop, &QEventLoop::quit);
request->send();
loop.exec();
if (request->getResult() != ResourceRequest::Success) {
qCDebug(commerce) << "Failed to get .app.json file from remote.";
return false;
}
// Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface
auto requestData = request->getData();
QFile appFile(APP_PATH + "/" + appHref.fileName());
if (!appFile.open(QIODevice::WriteOnly)) {
qCDebug(commerce) << "Couldn't open local .app.json file for creation.";
return false;
}
if (appFile.write(requestData) == -1) {
qCDebug(commerce) << "Couldn't write to local .app.json file.";
return false;
}
// Close the file
appFile.close();
// Read from the returned datastream to know what .js to add to Running Scripts
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(requestData);
QJsonObject appFileJsonObject = appFileJsonDocument.object();
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
qCDebug(commerce) << "Couldn't load script.";
return false;
}
emit appInstalled(appHref.fileName());
return true;
}
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());
if (!appFile.open(QIODevice::ReadOnly)) {
qCDebug(commerce) << "Couldn't open local .app.json file for deletion.";
return false;
}
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll());
QJsonObject appFileJsonObject = appFileJsonDocument.object();
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
if (!DependencyManager::get<ScriptEngines>()->stopScript(scriptUrl.trimmed(), false)) {
qCDebug(commerce) << "Couldn't stop script.";
return false;
}
// Delete the .app.json from the filesystem
// remove() closes the file first.
if (!appFile.remove()) {
qCDebug(commerce) << "Couldn't delete local .app.json file.";
return false;
}
emit appUninstalled(appHref.fileName());
return true;
}

View file

@ -51,6 +51,9 @@ signals:
void contentSetChanged(const QString& contentSetHref);
void appInstalled(const QString& appFileName);
void appUninstalled(const QString& appFileName);
protected:
Q_INVOKABLE void getWalletStatus();
@ -76,8 +79,11 @@ protected:
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
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);
};
#endif // hifi_QmlCommerce_h

View file

@ -551,11 +551,11 @@ var selectionDisplay = null; // for gridTool.js to ignore
break;
case 'checkout_rezClicked':
case 'purchases_rezClicked':
if (message.itemType === "app") {
console.log("How did you get here? You can't buy apps yet!");
} else {
rezEntity(message.itemHref, message.itemType);
}
rezEntity(message.itemHref, message.itemType);
break;
case 'checkout_installClicked':
case 'purchases_installClicked':
break;
case 'header_marketplaceImageClicked':
case 'purchases_backClicked':